Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1337)

Unified Diff: net/websockets/websocket_end_to_end_test.cc

Issue 722343003: Add end to end tests for WebSockets in net/websockets/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Disable the tests on Android. Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/net.gypi ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/websockets/websocket_end_to_end_test.cc
diff --git a/net/websockets/websocket_end_to_end_test.cc b/net/websockets/websocket_end_to_end_test.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a9ad4e09a52ff1af74d5ad36d018d60f59ef39aa
--- /dev/null
+++ b/net/websockets/websocket_end_to_end_test.cc
@@ -0,0 +1,284 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// End-to-end tests for WebSocket. Usage guidelines:
+// There are at least 4 sets of end-to-end tests in the source tree:
+// 1) Blink layout tests. These are easy to write, and efficient because the
+// client and server processes are both re-used. They are easy to write as
+// they are just Javascript. They should be used for the majority of
+// functional tests.
+// 2) Browser tests in //chrome/browser/net/websocket_browsertest.cc. These
+// are inefficient because both the server and client are restarted for each
+// test. They are also hard to write and hard to debug. They should generally
+// only be used for testing UI-related features.
+// 3) PPAPI tests in //chrome/test/ppapi/ppapi_browsertest.cc. These are
+// very hard to write and debug, and should only be used for verifying the
+// operation of the Pepper API.
+// 4) These tests. They are somewhat inefficient because the server is restarted
+// for each test. They are well-suited for tests which require special server
+// configurations.
+//
+// Tests should generally not be duplicated in the different places, except for
+// regression tests and basic smoke tests.
+
tyoshino (SeeGerritForStatus) 2015/01/05 08:45:48 string
Adam Rice 2015/01/06 12:27:15 Done.
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
+#include "net/base/auth.h"
+#include "net/base/network_delegate.h"
+#include "net/base/test_data_directory.h"
tyoshino (SeeGerritForStatus) 2015/01/05 08:47:29 net/proxy/proxy_service.h
Adam Rice 2015/01/06 12:27:15 Done.
+#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/url_request/url_request_test_util.h"
+#include "net/websockets/websocket_channel.h"
+#include "net/websockets/websocket_event_interface.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/origin.h"
+
+namespace net {
+
+namespace {
+
+static const char kEchoServer[] = "echo-with-no-extension";
+
+// An implementation of WebSocketEventInterface that waits for and records the
+// results of the connect.
+class ConnectTestingEventInterface : public WebSocketEventInterface {
+ public:
+ ConnectTestingEventInterface() : fail_(true) {}
+
+ void WaitForResponse() {
+ quit_closure_ = run_loop_.QuitClosure();
tyoshino (SeeGerritForStatus) 2015/01/05 08:45:48 quit_closure_ is initialized here to make DCHECK o
Adam Rice 2015/01/06 12:27:15 No, it was a mistake. I misunderstood the API of R
+ run_loop_.Run();
+ }
+
tyoshino (SeeGerritForStatus) 2015/01/05 08:45:48 explain that this variable is used for storing sev
Adam Rice 2015/01/06 12:27:15 I decided that setting fail_ in OnDropChannel() wa
+ bool fail() const { return fail_; }
+
+ // Only set if the handshake failed, otherwise empty.
+ // Failure messages appear on the console and are checked by the layout tests,
+ // so they are expected to stay reasonably stable across versions.
+ std::string failure_message() const { return failure_message_; }
+
+ std::string selected_subprotocol() const { return selected_subprotocol_; }
+
+ std::string extensions() const { return extensions_; }
+
+ ChannelState OnAddChannelResponse(bool fail,
+ const std::string& selected_subprotocol,
+ const std::string& extensions) override {
+ fail_ = fail;
+ selected_subprotocol_ = selected_subprotocol;
+ extensions_ = extensions;
+ QuitNestedEventLoop();
+ return fail ? CHANNEL_DELETED : CHANNEL_ALIVE;
+ }
+
+ ChannelState OnDataFrame(bool fin,
+ WebSocketMessageType type,
+ const std::vector<char>& data) override {
+ return CHANNEL_ALIVE;
+ }
+
+ ChannelState OnFlowControl(int64 quota) override { return CHANNEL_ALIVE; }
+
+ ChannelState OnClosingHandshake() override { return CHANNEL_ALIVE; }
+
+ ChannelState OnDropChannel(bool was_clean,
+ uint16 code,
+ const std::string& reason) override {
+ fail_ = !was_clean;
+ QuitNestedEventLoop();
+ return CHANNEL_DELETED;
+ }
+
+ ChannelState OnFailChannel(const std::string& message) override {
+ fail_ = true;
+ failure_message_ = message;
+ QuitNestedEventLoop();
+ return CHANNEL_DELETED;
+ }
+
+ ChannelState OnStartOpeningHandshake(
+ scoped_ptr<WebSocketHandshakeRequestInfo> request) override {
+ return CHANNEL_ALIVE;
+ }
+
+ ChannelState OnFinishOpeningHandshake(
+ scoped_ptr<WebSocketHandshakeResponseInfo> response) override {
+ return CHANNEL_ALIVE;
+ }
+
+ ChannelState OnSSLCertificateError(
+ scoped_ptr<SSLErrorCallbacks> ssl_error_callbacks,
+ const GURL& url,
+ const SSLInfo& ssl_info,
+ bool fatal) override {
+ ssl_error_callbacks->CancelSSLRequest(ERR_SSL_PROTOCOL_ERROR, &ssl_info);
tyoshino (SeeGerritForStatus) 2015/01/05 08:45:48 I'm a little worried about CancelSSLRequest() bein
Adam Rice 2015/01/06 12:27:15 I'm not 100% sure. I decided to call it via the Po
+ return CHANNEL_ALIVE;
+ }
+
+ private:
+ void QuitNestedEventLoop() {
+ DCHECK(!quit_closure_.is_null());
+ quit_closure_.Run();
+ }
+ bool fail_;
+ std::string selected_subprotocol_;
+ std::string extensions_;
+ std::string failure_message_;
+ base::RunLoop run_loop_;
+ base::Closure quit_closure_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConnectTestingEventInterface);
+};
+
+class WebSocketEndToEndTest : public ::testing::Test {
+ protected:
+ WebSocketEndToEndTest()
+ : event_interface_(new ConnectTestingEventInterface),
+ network_delegate_(new TestNetworkDelegate),
+ context_(true),
+ channel_(make_scoped_ptr(event_interface_), &context_),
+ origin_("http://localhost"),
+ initialised_context_(false) {}
+
+ void InitialiseContext() {
+ context_.set_network_delegate(network_delegate_.get());
+ context_.Init();
+ initialised_context_ = true;
+ }
+
+ bool ConnectAndWait(const GURL& socket_url) {
+ if (!initialised_context_) {
+ InitialiseContext();
+ }
+ channel_.SendAddChannelRequest(GURL(socket_url), sub_protocols_, origin_);
+ event_interface_->WaitForResponse();
+ return !event_interface_->fail();
+ }
+
+ ConnectTestingEventInterface* event_interface_; // owned by channel_
+ scoped_ptr<TestNetworkDelegate> network_delegate_;
+ TestURLRequestContext context_;
+ WebSocketChannel channel_;
+ std::vector<std::string> sub_protocols_;
+ url::Origin origin_;
tyoshino (SeeGerritForStatus) 2015/01/05 08:45:48 how about making sub_protocols_ and origin_ local
Adam Rice 2015/01/06 12:27:15 Done.
+ bool initialised_context_;
+};
+
+// None of these tests work on Android.
+// TODO(ricea): Make these tests work on Android. See crbug.com/441711.
+#if defined(OS_ANDROID)
+#define DISABLED_ON_ANDROID(test) DISABLED_##test
+#else
+#define DISABLED_ON_ANDROID(test) test
+#endif
+
+// Basic test of connectivity. If this test fails, nothing else can be expected
+// to work.
+TEST_F(WebSocketEndToEndTest, DISABLED_ON_ANDROID(BasicSmokeTest)) {
+ SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
+ SpawnedTestServer::kLocalhost,
+ GetWebSocketTestDataDirectory());
+ ASSERT_TRUE(ws_server.Start());
+ EXPECT_TRUE(ConnectAndWait(ws_server.GetURL(kEchoServer)));
+}
+
+// Test for issue crbug.com/433695 "Unencrypted WebSocket connection via
+// authenticated proxy times out"
+// TODO(ricea): Enable this when the issue is fixed.
+TEST_F(WebSocketEndToEndTest, DISABLED_HttpsProxyUnauthedFails) {
+ SpawnedTestServer proxy_server(SpawnedTestServer::TYPE_BASIC_AUTH_PROXY,
+ SpawnedTestServer::kLocalhost,
+ base::FilePath());
+ SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
+ SpawnedTestServer::kLocalhost,
+ GetWebSocketTestDataDirectory());
+ ASSERT_TRUE(proxy_server.StartInBackground());
+ ASSERT_TRUE(ws_server.StartInBackground());
+ ASSERT_TRUE(proxy_server.BlockUntilStarted());
+ ASSERT_TRUE(ws_server.BlockUntilStarted());
+ std::string proxy_config =
+ "https=" + proxy_server.host_port_pair().ToString();
+ scoped_ptr<ProxyService> proxy_service(
+ ProxyService::CreateFixed(proxy_config));
+ ASSERT_TRUE(proxy_service);
+ context_.set_proxy_service(proxy_service.get());
+ EXPECT_FALSE(ConnectAndWait(ws_server.GetURL(kEchoServer)));
+ EXPECT_EQ("Proxy authentication failed", event_interface_->failure_message());
+}
+
+TEST_F(WebSocketEndToEndTest, DISABLED_ON_ANDROID(HttpsWssProxyUnauthedFails)) {
+ SpawnedTestServer proxy_server(SpawnedTestServer::TYPE_BASIC_AUTH_PROXY,
+ SpawnedTestServer::kLocalhost,
+ base::FilePath());
+ SpawnedTestServer wss_server(SpawnedTestServer::TYPE_WSS,
+ SpawnedTestServer::kLocalhost,
+ GetWebSocketTestDataDirectory());
+ ASSERT_TRUE(proxy_server.StartInBackground());
+ ASSERT_TRUE(wss_server.StartInBackground());
+ ASSERT_TRUE(proxy_server.BlockUntilStarted());
+ ASSERT_TRUE(wss_server.BlockUntilStarted());
+ std::string proxy_config =
+ "https=" + proxy_server.host_port_pair().ToString();
+ scoped_ptr<ProxyService> proxy_service(
+ ProxyService::CreateFixed(proxy_config));
+ ASSERT_TRUE(proxy_service);
+ context_.set_proxy_service(proxy_service.get());
+ EXPECT_FALSE(ConnectAndWait(wss_server.GetURL(kEchoServer)));
+ EXPECT_EQ("Proxy authentication failed", event_interface_->failure_message());
+}
+
+// Regression test for crbug/426736 "WebSocket connections not using configured
+// system HTTPS Proxy".
+TEST_F(WebSocketEndToEndTest, DISABLED_ON_ANDROID(HttpsProxyUsed)) {
+ SpawnedTestServer proxy_server(SpawnedTestServer::TYPE_BASIC_AUTH_PROXY,
+ SpawnedTestServer::kLocalhost,
+ base::FilePath());
+ SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
+ SpawnedTestServer::kLocalhost,
+ GetWebSocketTestDataDirectory());
+ ASSERT_TRUE(proxy_server.StartInBackground());
+ ASSERT_TRUE(ws_server.StartInBackground());
+ ASSERT_TRUE(proxy_server.BlockUntilStarted());
+ ASSERT_TRUE(ws_server.BlockUntilStarted());
+ std::string proxy_config = "https=" +
+ proxy_server.host_port_pair().ToString() + ";" +
+ "http=" + proxy_server.host_port_pair().ToString();
+ scoped_ptr<ProxyService> proxy_service(
+ ProxyService::CreateFixed(proxy_config));
+ context_.set_proxy_service(proxy_service.get());
+ InitialiseContext();
+
+ // The test server doesn't have an unauthenticated proxy mode. WebSockets
+ // cannot provide auth information that isn't already cached, so it's
+ // necessary to preflight an HTTP request to authenticate against the proxy.
+ std::string scheme("http");
+ GURL::Replacements replacements;
+ replacements.SetSchemeStr(scheme);
+ // It doesn't matter what the URL is, as long as it is an HTTP navigation.
+ GURL http_page =
+ ws_server.GetURL("connect_check.html").ReplaceComponents(replacements);
+ TestDelegate delegate;
+ delegate.set_credentials(
+ AuthCredentials(base::ASCIIToUTF16("foo"), base::ASCIIToUTF16("bar")));
+ {
+ scoped_ptr<URLRequest> request(
+ context_.CreateRequest(http_page, DEFAULT_PRIORITY, &delegate, NULL));
+ request->Start();
+ // TestDelegate exits the message loop when the request completes by
+ // default.
+ base::RunLoop().Run();
+ EXPECT_TRUE(delegate.auth_required_called());
+ }
+
+ int previous_observed_before_proxy_headers_sent_callbacks =
+ network_delegate_->observed_before_proxy_headers_sent_callbacks();
+ EXPECT_TRUE(ConnectAndWait(ws_server.GetURL(kEchoServer)));
+ EXPECT_EQ(previous_observed_before_proxy_headers_sent_callbacks + 1,
+ network_delegate_->observed_before_proxy_headers_sent_callbacks());
tyoshino (SeeGerritForStatus) 2015/01/05 08:45:48 what does this expectations add? reading the varia
Adam Rice 2015/01/06 12:27:15 It works because of a bug. I'm still looking for a
Adam Rice 2015/01/06 15:48:43 I found a way to do it. PTAL.
+}
+
+} // namespace
+
+} // namespace net
« no previous file with comments | « net/net.gypi ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698