| Index: net/socket/websocket_endpoint_lock_manager_unittest.cc
|
| diff --git a/net/socket/websocket_endpoint_lock_manager_unittest.cc b/net/socket/websocket_endpoint_lock_manager_unittest.cc
|
| index 1626aa9020185e7e71929910e89d658c8718a73a..1603a3bf5cfef0dcfae83260e6b1eff0aa636f72 100644
|
| --- a/net/socket/websocket_endpoint_lock_manager_unittest.cc
|
| +++ b/net/socket/websocket_endpoint_lock_manager_unittest.cc
|
| @@ -4,6 +4,9 @@
|
|
|
| #include "net/socket/websocket_endpoint_lock_manager.h"
|
|
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "base/run_loop.h"
|
| +#include "base/time/time.h"
|
| #include "net/base/net_errors.h"
|
| #include "net/socket/next_proto.h"
|
| #include "net/socket/socket_test_util.h"
|
| @@ -89,11 +92,30 @@ class FakeWaiter : public WebSocketEndpointLockManager::Waiter {
|
| bool called_;
|
| };
|
|
|
| +class BlockingWaiter : public FakeWaiter {
|
| + public:
|
| + void WaitForLock() {
|
| + while (!called()) {
|
| + run_loop_.Run();
|
| + }
|
| + }
|
| +
|
| + void GotEndpointLock() override {
|
| + FakeWaiter::GotEndpointLock();
|
| + run_loop_.Quit();
|
| + }
|
| +
|
| + private:
|
| + base::RunLoop run_loop_;
|
| +};
|
| +
|
| class WebSocketEndpointLockManagerTest : public ::testing::Test {
|
| protected:
|
| WebSocketEndpointLockManagerTest()
|
| : instance_(WebSocketEndpointLockManager::GetInstance()) {}
|
| ~WebSocketEndpointLockManagerTest() override {
|
| + // Permit any pending asynchronous unlock operations to complete.
|
| + RunUntilIdle();
|
| // If this check fails then subsequent tests may fail.
|
| CHECK(instance_->IsEmpty());
|
| }
|
| @@ -109,10 +131,14 @@ class WebSocketEndpointLockManagerTest : public ::testing::Test {
|
| void UnlockDummyEndpoint(int times) {
|
| for (int i = 0; i < times; ++i) {
|
| instance()->UnlockEndpoint(DummyEndpoint());
|
| + RunUntilIdle();
|
| }
|
| }
|
|
|
| + static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
|
| +
|
| WebSocketEndpointLockManager* const instance_;
|
| + ScopedWebSocketEndpointZeroUnlockDelay zero_unlock_delay_;
|
| };
|
|
|
| TEST_F(WebSocketEndpointLockManagerTest, GetInstanceWorks) {
|
| @@ -131,6 +157,7 @@ TEST_F(WebSocketEndpointLockManagerTest, LockEndpointReturnsOkOnce) {
|
| TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockNotCalledOnOk) {
|
| FakeWaiter waiter;
|
| EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiter));
|
| + RunUntilIdle();
|
| EXPECT_FALSE(waiter.called());
|
|
|
| UnlockDummyEndpoint(1);
|
| @@ -141,6 +168,7 @@ TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockNotCalledImmediately) {
|
| EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiters[0]));
|
| EXPECT_EQ(ERR_IO_PENDING,
|
| instance()->LockEndpoint(DummyEndpoint(), &waiters[1]));
|
| + RunUntilIdle();
|
| EXPECT_FALSE(waiters[1].called());
|
|
|
| UnlockDummyEndpoint(2);
|
| @@ -152,6 +180,7 @@ TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockCalledWhenUnlocked) {
|
| EXPECT_EQ(ERR_IO_PENDING,
|
| instance()->LockEndpoint(DummyEndpoint(), &waiters[1]));
|
| instance()->UnlockEndpoint(DummyEndpoint());
|
| + RunUntilIdle();
|
| EXPECT_TRUE(waiters[1].called());
|
|
|
| UnlockDummyEndpoint(1);
|
| @@ -169,6 +198,7 @@ TEST_F(WebSocketEndpointLockManagerTest,
|
| }
|
|
|
| instance()->UnlockEndpoint(DummyEndpoint());
|
| + RunUntilIdle();
|
|
|
| FakeWaiter second_lock_holder;
|
| EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &second_lock_holder));
|
| @@ -185,6 +215,7 @@ TEST_F(WebSocketEndpointLockManagerTest, RememberSocketWorks) {
|
|
|
| instance()->RememberSocket(&dummy_socket, DummyEndpoint());
|
| instance()->UnlockSocket(&dummy_socket);
|
| + RunUntilIdle();
|
| EXPECT_TRUE(waiters[1].called());
|
|
|
| UnlockDummyEndpoint(1);
|
| @@ -199,6 +230,7 @@ TEST_F(WebSocketEndpointLockManagerTest, SocketAssociationForgottenOnUnlock) {
|
| EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiter));
|
| instance()->RememberSocket(&dummy_socket, DummyEndpoint());
|
| instance()->UnlockEndpoint(DummyEndpoint());
|
| + RunUntilIdle();
|
| EXPECT_TRUE(instance()->IsEmpty());
|
| }
|
|
|
| @@ -213,12 +245,72 @@ TEST_F(WebSocketEndpointLockManagerTest, NextWaiterCanCallRememberSocketAgain) {
|
|
|
| instance()->RememberSocket(&dummy_sockets[0], DummyEndpoint());
|
| instance()->UnlockEndpoint(DummyEndpoint());
|
| + RunUntilIdle();
|
| EXPECT_TRUE(waiters[1].called());
|
| instance()->RememberSocket(&dummy_sockets[1], DummyEndpoint());
|
|
|
| UnlockDummyEndpoint(1);
|
| }
|
|
|
| +// Calling UnlockSocket() after UnlockEndpoint() does nothing.
|
| +TEST_F(WebSocketEndpointLockManagerTest,
|
| + UnlockSocketAfterUnlockEndpointDoesNothing) {
|
| + FakeWaiter waiters[3];
|
| + FakeStreamSocket dummy_socket;
|
| +
|
| + EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiters[0]));
|
| + EXPECT_EQ(ERR_IO_PENDING,
|
| + instance()->LockEndpoint(DummyEndpoint(), &waiters[1]));
|
| + EXPECT_EQ(ERR_IO_PENDING,
|
| + instance()->LockEndpoint(DummyEndpoint(), &waiters[2]));
|
| + instance()->RememberSocket(&dummy_socket, DummyEndpoint());
|
| + instance()->UnlockEndpoint(DummyEndpoint());
|
| + instance()->UnlockSocket(&dummy_socket);
|
| + RunUntilIdle();
|
| + EXPECT_TRUE(waiters[1].called());
|
| + EXPECT_FALSE(waiters[2].called());
|
| +
|
| + UnlockDummyEndpoint(2);
|
| +}
|
| +
|
| +// UnlockEndpoint() should always be asynchronous.
|
| +TEST_F(WebSocketEndpointLockManagerTest, UnlockEndpointIsAsynchronous) {
|
| + FakeWaiter waiters[2];
|
| + EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiters[0]));
|
| + EXPECT_EQ(ERR_IO_PENDING,
|
| + instance()->LockEndpoint(DummyEndpoint(), &waiters[1]));
|
| +
|
| + instance()->UnlockEndpoint(DummyEndpoint());
|
| + EXPECT_FALSE(waiters[1].called());
|
| + RunUntilIdle();
|
| + EXPECT_TRUE(waiters[1].called());
|
| +
|
| + UnlockDummyEndpoint(1);
|
| +}
|
| +
|
| +// UnlockEndpoint() should normally have a delay.
|
| +TEST_F(WebSocketEndpointLockManagerTest, UnlockEndpointIsDelayed) {
|
| + using base::TimeTicks;
|
| +
|
| + const base::TimeDelta unlock_delay = base::TimeDelta::FromMilliseconds(1);
|
| + instance()->SetUnlockDelayForTesting(unlock_delay);
|
| + FakeWaiter fake_waiter;
|
| + BlockingWaiter blocking_waiter;
|
| + EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &fake_waiter));
|
| + EXPECT_EQ(ERR_IO_PENDING,
|
| + instance()->LockEndpoint(DummyEndpoint(), &blocking_waiter));
|
| +
|
| + TimeTicks before_unlock = TimeTicks::Now();
|
| + instance()->UnlockEndpoint(DummyEndpoint());
|
| + RunUntilIdle();
|
| + EXPECT_FALSE(blocking_waiter.called());
|
| + blocking_waiter.WaitForLock();
|
| + TimeTicks after_unlock = TimeTicks::Now();
|
| + EXPECT_GE(after_unlock - before_unlock, unlock_delay);
|
| + instance()->SetUnlockDelayForTesting(base::TimeDelta());
|
| + UnlockDummyEndpoint(1);
|
| +}
|
| +
|
| } // namespace
|
|
|
| } // namespace net
|
|
|