Home | History | Annotate | Download | only in net
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/net/connection_tester.h"
      6 
      7 #include "base/prefs/testing_pref_service.h"
      8 #include "content/public/browser/cookie_store_factory.h"
      9 #include "content/public/test/test_browser_thread.h"
     10 #include "content/public/browser/cookie_store_factory.h"
     11 #include "net/cert/mock_cert_verifier.h"
     12 #include "net/dns/mock_host_resolver.h"
     13 #include "net/ftp/ftp_network_layer.h"
     14 #include "net/http/http_auth_handler_factory.h"
     15 #include "net/http/http_network_layer.h"
     16 #include "net/http/http_network_session.h"
     17 #include "net/http/http_server_properties_impl.h"
     18 #include "net/http/transport_security_state.h"
     19 #include "net/proxy/proxy_config_service_fixed.h"
     20 #include "net/proxy/proxy_service.h"
     21 #include "net/ssl/ssl_config_service_defaults.h"
     22 #include "net/test/spawned_test_server/spawned_test_server.h"
     23 #include "net/url_request/url_request_context.h"
     24 #include "net/url_request/url_request_test_util.h"
     25 #include "testing/gtest/include/gtest/gtest.h"
     26 #include "testing/platform_test.h"
     27 
     28 using content::BrowserThread;
     29 
     30 namespace {
     31 
     32 // This is a testing delegate which simply counts how many times each of
     33 // the delegate's methods were invoked.
     34 class ConnectionTesterDelegate : public ConnectionTester::Delegate {
     35  public:
     36   ConnectionTesterDelegate()
     37      : start_connection_test_suite_count_(0),
     38        start_connection_test_experiment_count_(0),
     39        completed_connection_test_experiment_count_(0),
     40        completed_connection_test_suite_count_(0) {
     41   }
     42 
     43   virtual void OnStartConnectionTestSuite() OVERRIDE {
     44     start_connection_test_suite_count_++;
     45   }
     46 
     47   virtual void OnStartConnectionTestExperiment(
     48       const ConnectionTester::Experiment& experiment) OVERRIDE {
     49     start_connection_test_experiment_count_++;
     50   }
     51 
     52   virtual void OnCompletedConnectionTestExperiment(
     53       const ConnectionTester::Experiment& experiment,
     54       int result) OVERRIDE {
     55     completed_connection_test_experiment_count_++;
     56   }
     57 
     58   virtual void OnCompletedConnectionTestSuite() OVERRIDE {
     59     completed_connection_test_suite_count_++;
     60     base::MessageLoop::current()->Quit();
     61   }
     62 
     63   int start_connection_test_suite_count() const {
     64     return start_connection_test_suite_count_;
     65   }
     66 
     67   int start_connection_test_experiment_count() const {
     68     return start_connection_test_experiment_count_;
     69   }
     70 
     71   int completed_connection_test_experiment_count() const {
     72     return completed_connection_test_experiment_count_;
     73   }
     74 
     75   int completed_connection_test_suite_count() const {
     76     return completed_connection_test_suite_count_;
     77   }
     78 
     79  private:
     80   int start_connection_test_suite_count_;
     81   int start_connection_test_experiment_count_;
     82   int completed_connection_test_experiment_count_;
     83   int completed_connection_test_suite_count_;
     84 };
     85 
     86 // The test fixture is responsible for:
     87 //   - Making sure each test has an IO loop running
     88 //   - Catching any host resolve requests and mapping them to localhost
     89 //     (so the test doesn't use any external network dependencies).
     90 class ConnectionTesterTest : public PlatformTest {
     91  public:
     92   ConnectionTesterTest()
     93       : io_thread_(BrowserThread::IO, &message_loop_),
     94         test_server_(net::SpawnedTestServer::TYPE_HTTP,
     95                      net::SpawnedTestServer::kLocalhost,
     96                      // Nothing is read in this directory.
     97                      base::FilePath(FILE_PATH_LITERAL("chrome"))) {
     98   }
     99 
    100  protected:
    101   // Destroy last the MessageLoop last to give a chance for objects like
    102   // ObserverListThreadSave to shut down properly.  For example,
    103   // SSLClientAuthCache calls RemoveObserver when destroyed, but if the
    104   // MessageLoop is already destroyed, then the RemoveObserver will be a
    105   // no-op, and the ObserverList will contain invalid entries.
    106   base::MessageLoopForIO message_loop_;
    107   content::TestBrowserThread io_thread_;
    108   net::SpawnedTestServer test_server_;
    109   net::TestURLRequestContext proxy_script_fetcher_context_;
    110   ConnectionTesterDelegate test_delegate_;
    111 };
    112 
    113 TEST_F(ConnectionTesterTest, RunAllTests) {
    114   ASSERT_TRUE(test_server_.Start());
    115 
    116   ConnectionTester tester(&test_delegate_,
    117                           &proxy_script_fetcher_context_,
    118                           NULL);
    119 
    120   // Start the test suite on URL "echoall".
    121   // TODO(eroman): Is this URL right?
    122   tester.RunAllTests(test_server_.GetURL("echoall"));
    123 
    124   // Wait for all the tests to complete.
    125   base::MessageLoop::current()->Run();
    126 
    127   const int kNumExperiments =
    128       ConnectionTester::PROXY_EXPERIMENT_COUNT *
    129       ConnectionTester::HOST_RESOLVER_EXPERIMENT_COUNT;
    130 
    131   EXPECT_EQ(1, test_delegate_.start_connection_test_suite_count());
    132   EXPECT_EQ(kNumExperiments,
    133             test_delegate_.start_connection_test_experiment_count());
    134   EXPECT_EQ(kNumExperiments,
    135             test_delegate_.completed_connection_test_experiment_count());
    136   EXPECT_EQ(1, test_delegate_.completed_connection_test_suite_count());
    137 }
    138 
    139 TEST_F(ConnectionTesterTest, DeleteWhileInProgress) {
    140   ASSERT_TRUE(test_server_.Start());
    141 
    142   scoped_ptr<ConnectionTester> tester(
    143       new ConnectionTester(&test_delegate_,
    144                            &proxy_script_fetcher_context_,
    145                            NULL));
    146 
    147   // Start the test suite on URL "echoall".
    148   // TODO(eroman): Is this URL right?
    149   tester->RunAllTests(test_server_.GetURL("echoall"));
    150 
    151   // Don't run the message loop at all.  Otherwise the experiment's request may
    152   // complete and post a task to run the next experiment before we quit the
    153   // message loop.
    154 
    155   EXPECT_EQ(1, test_delegate_.start_connection_test_suite_count());
    156   EXPECT_EQ(1, test_delegate_.start_connection_test_experiment_count());
    157   EXPECT_EQ(0, test_delegate_.completed_connection_test_experiment_count());
    158   EXPECT_EQ(0, test_delegate_.completed_connection_test_suite_count());
    159 
    160   // Delete the ConnectionTester while it is in progress.
    161   tester.reset();
    162 
    163   // Drain the tasks on the message loop.
    164   //
    165   // Note that we cannot simply stop the message loop, since that will delete
    166   // any pending tasks instead of running them. This causes a problem with
    167   // net::ClientSocketPoolBaseHelper, since the "Group" holds a pointer
    168   // |backup_task| that it will try to deref during the destructor, but
    169   // depending on the order that pending tasks were deleted in, it might
    170   // already be invalid! See http://crbug.com/43291.
    171   base::MessageLoop::current()->PostTask(FROM_HERE,
    172                                          base::MessageLoop::QuitClosure());
    173   base::MessageLoop::current()->Run();
    174 }
    175 
    176 }  // namespace
    177