| Index: remoting/host/security_key/security_key_auth_handler_linux_unittest.cc
|
| diff --git a/remoting/host/security_key/security_key_auth_handler_linux_unittest.cc b/remoting/host/security_key/security_key_auth_handler_linux_unittest.cc
|
| index 1d36b286f5ff2c99241924b8ff2607afa4415bb7..85798f88123a071dc9f1988f7b4ca9574c12db1b 100644
|
| --- a/remoting/host/security_key/security_key_auth_handler_linux_unittest.cc
|
| +++ b/remoting/host/security_key/security_key_auth_handler_linux_unittest.cc
|
| @@ -4,12 +4,15 @@
|
|
|
| #include <stddef.h>
|
|
|
| +#include "base/bind.h"
|
| +#include "base/bind_helpers.h"
|
| #include "base/files/file_path.h"
|
| #include "base/files/scoped_temp_dir.h"
|
| #include "base/macros.h"
|
| #include "base/message_loop/message_loop.h"
|
| #include "base/run_loop.h"
|
| #include "base/strings/stringprintf.h"
|
| +#include "base/threading/thread.h"
|
| #include "base/timer/mock_timer.h"
|
| #include "base/values.h"
|
| #include "net/base/io_buffer.h"
|
| @@ -25,6 +28,8 @@ namespace remoting {
|
|
|
| namespace {
|
|
|
| +const size_t kReadBufferSize = 1;
|
| +
|
| const char kSocketFilename[] = "socket_for_testing";
|
|
|
| // Test security key request data.
|
| @@ -48,75 +53,38 @@ const unsigned char kRequestData[] = {
|
|
|
| class SecurityKeyAuthHandlerLinuxTest : public testing::Test {
|
| public:
|
| - SecurityKeyAuthHandlerLinuxTest()
|
| - : run_loop_(new base::RunLoop()), last_connection_id_received_(-1) {
|
| - EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
|
| - socket_path_ = temp_dir_.path().Append(kSocketFilename);
|
| - remoting::SecurityKeyAuthHandler::SetSecurityKeySocketName(socket_path_);
|
| -
|
| - send_message_callback_ =
|
| - base::Bind(&SecurityKeyAuthHandlerLinuxTest::SendMessageToClient,
|
| - base::Unretained(this));
|
| - auth_handler_ = remoting::SecurityKeyAuthHandler::Create(
|
| - nullptr, send_message_callback_);
|
| - }
|
| + SecurityKeyAuthHandlerLinuxTest();
|
|
|
| - void WaitForSendMessageToClient() {
|
| - run_loop_->Run();
|
| - run_loop_.reset(new base::RunLoop);
|
| - }
|
| -
|
| - void SendMessageToClient(int connection_id, const std::string& data) {
|
| - last_connection_id_received_ = connection_id;
|
| - last_message_received_ = data;
|
| - run_loop_->Quit();
|
| - }
|
| + // Creates a new socket and waits until it is ready to accept new connections.
|
| + void CreateSocketAndWait();
|
|
|
| - void CheckHostDataMessage(int id, const std::string& expected_data) {
|
| - ASSERT_EQ(id, last_connection_id_received_);
|
| - ASSERT_EQ(expected_data.length(), last_message_received_.length());
|
| - ASSERT_EQ(expected_data, last_message_received_);
|
| - }
|
| + // Used as a callback |auth_handler_|, stores the values received.
|
| + void SendMessageToClient(int connection_id, const std::string& data);
|
|
|
| - void WriteRequestData(net::UnixDomainClientSocket* client_socket) {
|
| - int request_len = sizeof(kRequestData);
|
| - scoped_refptr<net::DrainableIOBuffer> request_buffer(
|
| - new net::DrainableIOBuffer(
|
| - new net::WrappedIOBuffer(
|
| - reinterpret_cast<const char*>(kRequestData)),
|
| - request_len));
|
| - net::TestCompletionCallback write_callback;
|
| - int bytes_written = 0;
|
| - while (bytes_written < request_len) {
|
| - int write_result = client_socket->Write(request_buffer.get(),
|
| - request_buffer->BytesRemaining(),
|
| - write_callback.callback());
|
| - write_result = write_callback.GetResult(write_result);
|
| - ASSERT_GT(write_result, 0);
|
| - bytes_written += write_result;
|
| - ASSERT_LE(bytes_written, request_len);
|
| - request_buffer->DidConsume(write_result);
|
| - }
|
| - ASSERT_EQ(request_len, bytes_written);
|
| - }
|
| + // Writes |kRequestData| to |client_socket|.
|
| + void WriteRequestData(net::UnixDomainClientSocket* client_socket);
|
|
|
| - void WaitForAndVerifyHostMessage(int connection_id) {
|
| - WaitForSendMessageToClient();
|
| - std::string expected_data;
|
| - expected_data.reserve(sizeof(kRequestData) - 4);
|
| + // Helper method which validates message data once it has been received.
|
| + void WaitForAndVerifyHostMessage(int connection_id);
|
|
|
| - // Skip first four bytes and build up the response string.
|
| - for (size_t i = 4; i < sizeof(kRequestData); ++i) {
|
| - expected_data.append(1, static_cast<unsigned char>(kRequestData[i]));
|
| - }
|
| + // Waits until all existing posted tasks on |file_thread_| have been run.
|
| + void WaitForExistingSocketOperations();
|
|
|
| - CheckHostDataMessage(connection_id, expected_data);
|
| - }
|
| + // Waits until |client_socket| has been closed.
|
| + void WaitForConnectionClosed(net::UnixDomainClientSocket* client_socket);
|
|
|
| protected:
|
| + // Waits for |SendMessageToClient()| to be signaled.
|
| + void WaitForSendMessageToClient();
|
| +
|
| + // Verfies the data passed to the |SendMessageToClient| callback was valid.
|
| + void CheckHostDataMessage(int id, const std::string& expected_data);
|
| +
|
| base::MessageLoopForIO message_loop_;
|
| std::unique_ptr<base::RunLoop> run_loop_;
|
|
|
| + base::Thread file_thread_;
|
| +
|
| // Object under test.
|
| std::unique_ptr<SecurityKeyAuthHandler> auth_handler_;
|
|
|
| @@ -133,16 +101,127 @@ class SecurityKeyAuthHandlerLinuxTest : public testing::Test {
|
| DISALLOW_COPY_AND_ASSIGN(SecurityKeyAuthHandlerLinuxTest);
|
| };
|
|
|
| -TEST_F(SecurityKeyAuthHandlerLinuxTest, NotClosedAfterRequest) {
|
| +SecurityKeyAuthHandlerLinuxTest::SecurityKeyAuthHandlerLinuxTest()
|
| + : run_loop_(new base::RunLoop()),
|
| + file_thread_("SecurityKeyAuthHandlerLinuxTest_FileThread"),
|
| + last_connection_id_received_(-1) {
|
| + EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
|
| + socket_path_ = temp_dir_.path().Append(kSocketFilename);
|
| + remoting::SecurityKeyAuthHandler::SetSecurityKeySocketName(socket_path_);
|
| +
|
| + file_thread_.StartWithOptions(
|
| + base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
|
| +
|
| + send_message_callback_ =
|
| + base::Bind(&SecurityKeyAuthHandlerLinuxTest::SendMessageToClient,
|
| + base::Unretained(this));
|
| +
|
| + auth_handler_ = remoting::SecurityKeyAuthHandler::Create(
|
| + /*client_session_details=*/nullptr, send_message_callback_,
|
| + file_thread_.task_runner());
|
| +}
|
| +
|
| +void SecurityKeyAuthHandlerLinuxTest::WaitForExistingSocketOperations() {
|
| + ASSERT_TRUE(file_thread_.task_runner()->PostTaskAndReply(
|
| + FROM_HERE, base::Bind(&base::DoNothing), run_loop_->QuitClosure()));
|
| + run_loop_->Run();
|
| + run_loop_.reset(new base::RunLoop);
|
| +}
|
| +
|
| +void SecurityKeyAuthHandlerLinuxTest::CreateSocketAndWait() {
|
| ASSERT_EQ(0u, auth_handler_->GetActiveConnectionCountForTest());
|
|
|
| auth_handler_->CreateSecurityKeyConnection();
|
| + WaitForExistingSocketOperations();
|
| +
|
| + ASSERT_EQ(0u, auth_handler_->GetActiveConnectionCountForTest());
|
| +}
|
| +
|
| +void SecurityKeyAuthHandlerLinuxTest::SendMessageToClient(
|
| + int connection_id,
|
| + const std::string& data) {
|
| + last_connection_id_received_ = connection_id;
|
| + last_message_received_ = data;
|
| + run_loop_->Quit();
|
| +}
|
| +
|
| +void SecurityKeyAuthHandlerLinuxTest::WaitForSendMessageToClient() {
|
| + run_loop_->Run();
|
| + run_loop_.reset(new base::RunLoop);
|
| +}
|
| +
|
| +void SecurityKeyAuthHandlerLinuxTest::WriteRequestData(
|
| + net::UnixDomainClientSocket* client_socket) {
|
| + int request_len = sizeof(kRequestData);
|
| + scoped_refptr<net::DrainableIOBuffer> request_buffer(
|
| + new net::DrainableIOBuffer(
|
| + new net::WrappedIOBuffer(reinterpret_cast<const char*>(kRequestData)),
|
| + request_len));
|
| + net::TestCompletionCallback write_callback;
|
| + int bytes_written = 0;
|
| + while (bytes_written < request_len) {
|
| + int write_result = client_socket->Write(request_buffer.get(),
|
| + request_buffer->BytesRemaining(),
|
| + write_callback.callback());
|
| + write_result = write_callback.GetResult(write_result);
|
| + ASSERT_GT(write_result, 0);
|
| + bytes_written += write_result;
|
| + ASSERT_LE(bytes_written, request_len);
|
| + request_buffer->DidConsume(write_result);
|
| + }
|
| + ASSERT_EQ(request_len, bytes_written);
|
| +}
|
| +
|
| +void SecurityKeyAuthHandlerLinuxTest::CheckHostDataMessage(
|
| + int id,
|
| + const std::string& expected_data) {
|
| + ASSERT_EQ(id, last_connection_id_received_);
|
| + ASSERT_EQ(expected_data.length(), last_message_received_.length());
|
| + ASSERT_EQ(expected_data, last_message_received_);
|
| +}
|
| +
|
| +void SecurityKeyAuthHandlerLinuxTest::WaitForAndVerifyHostMessage(
|
| + int connection_id) {
|
| + WaitForSendMessageToClient();
|
| + std::string expected_data;
|
| + expected_data.reserve(sizeof(kRequestData) - 4);
|
| +
|
| + // Skip first four bytes and build up the response string.
|
| + for (size_t i = 4; i < sizeof(kRequestData); ++i) {
|
| + expected_data.append(1, static_cast<unsigned char>(kRequestData[i]));
|
| + }
|
| +
|
| + CheckHostDataMessage(connection_id, expected_data);
|
| +}
|
| +
|
| +void SecurityKeyAuthHandlerLinuxTest::WaitForConnectionClosed(
|
| + net::UnixDomainClientSocket* client_socket) {
|
| + // Ensure there are no pending operations.
|
| + WaitForExistingSocketOperations();
|
| +
|
| + // Create a blocking read operation to wait until the socket has been closed.
|
| + scoped_refptr<net::IOBuffer> read_buffer(new net::IOBuffer(kReadBufferSize));
|
| + net::TestCompletionCallback read_callback;
|
| + int read_result = client_socket->Read(read_buffer.get(), kReadBufferSize,
|
| + read_callback.callback());
|
| +
|
| + // GetResult blocks until the IO is no longer pending.
|
| + read_result = read_callback.GetResult(read_result);
|
| + ASSERT_EQ(read_result, static_cast<int>(kReadBufferSize));
|
| + ASSERT_TRUE(std::string(read_buffer->data()).empty());
|
| +
|
| + // Ensure all current and pending operations are complete.
|
| + WaitForExistingSocketOperations();
|
| +}
|
| +
|
| +TEST_F(SecurityKeyAuthHandlerLinuxTest, NotClosedAfterRequest) {
|
| + CreateSocketAndWait();
|
|
|
| net::UnixDomainClientSocket client_socket(socket_path_.value(), false);
|
| net::TestCompletionCallback connect_callback;
|
| -
|
| int rv = client_socket.Connect(connect_callback.callback());
|
| ASSERT_EQ(net::OK, connect_callback.GetResult(rv));
|
| + WaitForExistingSocketOperations();
|
|
|
| // Write the request and verify the response.
|
| WriteRequestData(&client_socket);
|
| @@ -156,15 +235,13 @@ TEST_F(SecurityKeyAuthHandlerLinuxTest, NotClosedAfterRequest) {
|
| }
|
|
|
| TEST_F(SecurityKeyAuthHandlerLinuxTest, HandleTwoRequests) {
|
| - ASSERT_EQ(0u, auth_handler_->GetActiveConnectionCountForTest());
|
| -
|
| - auth_handler_->CreateSecurityKeyConnection();
|
| + CreateSocketAndWait();
|
|
|
| net::UnixDomainClientSocket client_socket(socket_path_.value(), false);
|
| net::TestCompletionCallback connect_callback;
|
| -
|
| int rv = client_socket.Connect(connect_callback.callback());
|
| ASSERT_EQ(net::OK, connect_callback.GetResult(rv));
|
| + WaitForExistingSocketOperations();
|
|
|
| // Write the request and verify the response.
|
| WriteRequestData(&client_socket);
|
| @@ -186,15 +263,13 @@ TEST_F(SecurityKeyAuthHandlerLinuxTest, HandleTwoRequests) {
|
| }
|
|
|
| TEST_F(SecurityKeyAuthHandlerLinuxTest, HandleTwoIndependentRequests) {
|
| - ASSERT_EQ(0u, auth_handler_->GetActiveConnectionCountForTest());
|
| -
|
| - auth_handler_->CreateSecurityKeyConnection();
|
| + CreateSocketAndWait();
|
|
|
| net::UnixDomainClientSocket client_socket(socket_path_.value(), false);
|
| net::TestCompletionCallback connect_callback;
|
| -
|
| int rv = client_socket.Connect(connect_callback.callback());
|
| ASSERT_EQ(net::OK, connect_callback.GetResult(rv));
|
| + WaitForExistingSocketOperations();
|
|
|
| // Write the request and verify the response.
|
| WriteRequestData(&client_socket);
|
| @@ -207,6 +282,7 @@ TEST_F(SecurityKeyAuthHandlerLinuxTest, HandleTwoIndependentRequests) {
|
| client_socket.Disconnect();
|
| rv = client_socket.Connect(connect_callback.callback());
|
| ASSERT_EQ(net::OK, connect_callback.GetResult(rv));
|
| + WaitForExistingSocketOperations();
|
|
|
| // Repeat the request/response cycle.
|
| WriteRequestData(&client_socket);
|
| @@ -220,28 +296,64 @@ TEST_F(SecurityKeyAuthHandlerLinuxTest, HandleTwoIndependentRequests) {
|
| ASSERT_EQ(1u, auth_handler_->GetActiveConnectionCountForTest());
|
| }
|
|
|
| -TEST_F(SecurityKeyAuthHandlerLinuxTest, DidReadTimeout) {
|
| +TEST_F(SecurityKeyAuthHandlerLinuxTest, HandleNumerousIndependentRequests) {
|
| + CreateSocketAndWait();
|
| +
|
| + net::UnixDomainClientSocket client_socket(socket_path_.value(), false);
|
| + net::TestCompletionCallback connect_callback;
|
| +
|
| + // Connection IDs start at 1 so start there to simplify the rest of the code.
|
| + for (int i = 1; i < 11; i++) {
|
| + int rv = client_socket.Connect(connect_callback.callback());
|
| + ASSERT_EQ(net::OK, connect_callback.GetResult(rv));
|
| + WaitForExistingSocketOperations();
|
| +
|
| + // Verify the connection is now valid.
|
| + ASSERT_TRUE(auth_handler_->IsValidConnectionId(i));
|
| +
|
| + // Write the request and verify the response.
|
| + WriteRequestData(&client_socket);
|
| + WaitForAndVerifyHostMessage(i);
|
| +
|
| + // Disconnect and establish a new connection.
|
| + client_socket.Disconnect();
|
| + WaitForExistingSocketOperations();
|
| +
|
| + ASSERT_FALSE(auth_handler_->IsValidConnectionId(i));
|
| + }
|
| +
|
| + // Verify that the initial sockets were released properly.
|
| ASSERT_EQ(0u, auth_handler_->GetActiveConnectionCountForTest());
|
| - auth_handler_->CreateSecurityKeyConnection();
|
| +}
|
| +
|
| +TEST_F(SecurityKeyAuthHandlerLinuxTest, DidReadTimeout) {
|
| + auth_handler_->SetRequestTimeoutForTest(base::TimeDelta());
|
| +
|
| + CreateSocketAndWait();
|
|
|
| net::UnixDomainClientSocket client_socket(socket_path_.value(), false);
|
| net::TestCompletionCallback connect_callback;
|
| int rv = client_socket.Connect(connect_callback.callback());
|
| ASSERT_EQ(net::OK, connect_callback.GetResult(rv));
|
| - auth_handler_->SetRequestTimeoutForTest(base::TimeDelta());
|
| + WaitForConnectionClosed(&client_socket);
|
| +
|
| ASSERT_EQ(0u, auth_handler_->GetActiveConnectionCountForTest());
|
| }
|
|
|
| TEST_F(SecurityKeyAuthHandlerLinuxTest, ClientErrorMessageDelivered) {
|
| - ASSERT_EQ(0u, auth_handler_->GetActiveConnectionCountForTest());
|
| - auth_handler_->CreateSecurityKeyConnection();
|
| + CreateSocketAndWait();
|
|
|
| net::UnixDomainClientSocket client_socket(socket_path_.value(), false);
|
| net::TestCompletionCallback connect_callback;
|
| int rv = client_socket.Connect(connect_callback.callback());
|
| ASSERT_EQ(net::OK, connect_callback.GetResult(rv));
|
| + WaitForExistingSocketOperations();
|
| +
|
| + ASSERT_EQ(1u, auth_handler_->GetActiveConnectionCountForTest());
|
|
|
| auth_handler_->SendErrorAndCloseConnection(1);
|
| + WaitForConnectionClosed(&client_socket);
|
| +
|
| ASSERT_EQ(0u, auth_handler_->GetActiveConnectionCountForTest());
|
| }
|
|
|
|
|