Home | History | Annotate | Download | only in test
      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 "base/bind.h"
      6 #include "base/files/file_path.h"
      7 #include "base/logging.h"
      8 #include "base/path_service.h"
      9 #include "base/strings/string_util.h"
     10 #include "base/strings/stringprintf.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "base/sys_info.h"
     13 #include "base/test/test_timeouts.h"
     14 #include "content/browser/worker_host/worker_process_host.h"
     15 #include "content/browser/worker_host/worker_service_impl.h"
     16 #include "content/public/browser/browser_thread.h"
     17 #include "content/public/common/content_paths.h"
     18 #include "content/public/test/browser_test_utils.h"
     19 #include "content/public/test/test_utils.h"
     20 #include "content/shell/shell.h"
     21 #include "content/shell/shell_content_browser_client.h"
     22 #include "content/shell/shell_resource_dispatcher_host_delegate.h"
     23 #include "content/test/content_browser_test.h"
     24 #include "content/test/content_browser_test_utils.h"
     25 #include "net/base/test_data_directory.h"
     26 #include "net/test/spawned_test_server/spawned_test_server.h"
     27 #include "url/gurl.h"
     28 
     29 namespace content {
     30 
     31 class WorkerTest : public ContentBrowserTest {
     32  public:
     33   WorkerTest() {}
     34 
     35   GURL GetTestURL(const std::string& test_case, const std::string& query) {
     36     base::FilePath test_file_path = GetTestFilePath(
     37         "workers", test_case.c_str());
     38     return GetFileUrlWithQuery(test_file_path, query);
     39   }
     40 
     41   void RunTest(Shell* window,
     42                const std::string& test_case,
     43                const std::string& query) {
     44     GURL url = GetTestURL(test_case, query);
     45     const string16 expected_title = ASCIIToUTF16("OK");
     46     TitleWatcher title_watcher(window->web_contents(), expected_title);
     47     NavigateToURL(window, url);
     48     string16 final_title = title_watcher.WaitAndGetTitle();
     49     EXPECT_EQ(expected_title, final_title);
     50   }
     51 
     52   void RunTest(const std::string& test_case, const std::string& query) {
     53     RunTest(shell(), test_case, query);
     54   }
     55 
     56   static void CountWorkerProcesses(int *cur_process_count) {
     57     *cur_process_count = 0;
     58     for (WorkerProcessHostIterator iter; !iter.Done(); ++iter)
     59       (*cur_process_count)++;
     60     BrowserThread::PostTask(
     61         BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
     62   }
     63 
     64   bool WaitForWorkerProcessCount(int count) {
     65     int cur_process_count;
     66     for (int i = 0; i < 100; ++i) {
     67       BrowserThread::PostTask(
     68           BrowserThread::IO, FROM_HERE,
     69           base::Bind(&CountWorkerProcesses, &cur_process_count));
     70 
     71       RunMessageLoop();
     72       if (cur_process_count == count)
     73         return true;
     74 
     75       // Sometimes the worker processes can take a while to shut down on the
     76       // bots, so use a longer timeout period to avoid spurious failures.
     77       base::PlatformThread::Sleep(TestTimeouts::action_max_timeout() / 100);
     78     }
     79 
     80     EXPECT_EQ(cur_process_count, count);
     81     return false;
     82   }
     83 
     84   static void QuitUIMessageLoop(base::Callback<void()> callback) {
     85     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
     86   }
     87 
     88   void NavigateAndWaitForAuth(const GURL& url) {
     89     ShellContentBrowserClient* browser_client =
     90         ShellContentBrowserClient::Get();
     91     scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner();
     92     browser_client->resource_dispatcher_host_delegate()->
     93         set_login_request_callback(
     94             base::Bind(&QuitUIMessageLoop, runner->QuitClosure()));
     95     shell()->LoadURL(url);
     96     runner->Run();
     97   }
     98 };
     99 
    100 IN_PROC_BROWSER_TEST_F(WorkerTest, SingleWorker) {
    101   RunTest("single_worker.html", std::string());
    102 }
    103 
    104 IN_PROC_BROWSER_TEST_F(WorkerTest, MultipleWorkers) {
    105   RunTest("multi_worker.html", std::string());
    106 }
    107 
    108 IN_PROC_BROWSER_TEST_F(WorkerTest, SingleSharedWorker) {
    109   RunTest("single_worker.html", "shared=true");
    110 }
    111 
    112 // http://crbug.com/96435
    113 IN_PROC_BROWSER_TEST_F(WorkerTest, MultipleSharedWorkers) {
    114   RunTest("multi_worker.html", "shared=true");
    115 }
    116 
    117 // Incognito windows should not share workers with non-incognito windows
    118 // http://crbug.com/30021
    119 IN_PROC_BROWSER_TEST_F(WorkerTest, IncognitoSharedWorkers) {
    120   // Load a non-incognito tab and have it create a shared worker
    121   RunTest("incognito_worker.html", std::string());
    122 
    123   // Incognito worker should not share with non-incognito
    124   RunTest(CreateOffTheRecordBrowser(), "incognito_worker.html", std::string());
    125 }
    126 
    127 // Make sure that auth dialog is displayed from worker context.
    128 // http://crbug.com/33344
    129 IN_PROC_BROWSER_TEST_F(WorkerTest, WorkerHttpAuth) {
    130   ASSERT_TRUE(test_server()->Start());
    131   GURL url = test_server()->GetURL("files/workers/worker_auth.html");
    132 
    133   NavigateAndWaitForAuth(url);
    134 }
    135 
    136 // Make sure that auth dialog is displayed from shared worker context.
    137 // http://crbug.com/33344
    138 IN_PROC_BROWSER_TEST_F(WorkerTest, SharedWorkerHttpAuth) {
    139   ASSERT_TRUE(test_server()->Start());
    140   GURL url = test_server()->GetURL("files/workers/shared_worker_auth.html");
    141   NavigateAndWaitForAuth(url);
    142 }
    143 
    144 #if defined(OS_LINUX) || defined(OS_CHROMEOS)
    145 // This test is flaky inside the Linux SUID sandbox.
    146 // http://crbug.com/130116
    147 IN_PROC_BROWSER_TEST_F(WorkerTest, DISABLED_LimitPerPage) {
    148 #else
    149 IN_PROC_BROWSER_TEST_F(WorkerTest, LimitPerPage) {
    150 #endif
    151   int max_workers_per_tab = WorkerServiceImpl::kMaxWorkersPerTabWhenSeparate;
    152   std::string query = base::StringPrintf("?count=%d", max_workers_per_tab + 1);
    153 
    154   GURL url = GetTestURL("many_shared_workers.html", query);
    155   NavigateToURL(shell(), url);
    156   ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab));
    157 }
    158 
    159 #if defined(OS_LINUX) || defined(OS_CHROMEOS)
    160 // This test is flaky inside the Linux SUID sandbox.
    161 // http://crbug.com/130116
    162 IN_PROC_BROWSER_TEST_F(WorkerTest, DISABLED_LimitTotal) {
    163 #else
    164 // http://crbug.com/36800
    165 IN_PROC_BROWSER_TEST_F(WorkerTest, LimitTotal) {
    166 #endif
    167   if (base::SysInfo::AmountOfPhysicalMemoryMB() < 8192) {
    168     LOG(INFO) << "WorkerTest.LimitTotal not running because it needs 8 GB RAM.";
    169     return;
    170   }
    171 
    172   int max_workers_per_tab = WorkerServiceImpl::kMaxWorkersPerTabWhenSeparate;
    173   int total_workers = WorkerServiceImpl::kMaxWorkersWhenSeparate;
    174 
    175   std::string query = base::StringPrintf("?count=%d", max_workers_per_tab);
    176   GURL url = GetTestURL("many_shared_workers.html", query);
    177   NavigateToURL(shell(),
    178                 GURL(url.spec() + base::StringPrintf("&client_id=0")));
    179 
    180   // Adding 1 so that we cause some workers to be queued.
    181   int tab_count = (total_workers / max_workers_per_tab) + 1;
    182   for (int i = 1; i < tab_count; ++i) {
    183     NavigateToURL(
    184         CreateBrowser(),
    185         GURL(url.spec() + base::StringPrintf("&client_id=%d", i)));
    186   }
    187 
    188   // Check that we didn't create more than the max number of workers.
    189   ASSERT_TRUE(WaitForWorkerProcessCount(total_workers));
    190 
    191   // Now close a page and check that the queued workers were started.
    192   url = GURL(GetTestUrl("google", "google.html"));
    193   NavigateToURL(shell(), url);
    194 
    195   ASSERT_TRUE(WaitForWorkerProcessCount(total_workers));
    196 }
    197 
    198 // Flaky, http://crbug.com/59786.
    199 IN_PROC_BROWSER_TEST_F(WorkerTest, WorkerClose) {
    200   RunTest("worker_close.html", std::string());
    201   ASSERT_TRUE(WaitForWorkerProcessCount(0));
    202 }
    203 
    204 // Flaky, http://crbug.com/70861.
    205 // Times out regularly on Windows debug bots. See http://crbug.com/212339 .
    206 #if defined(OS_WIN) && !defined(NDEBUG)
    207 #define MAYBE_QueuedSharedWorkerShutdown DISABLED_QueuedSharedWorkerShutdown
    208 #else
    209 #define MAYBE_QueuedSharedWorkerShutdown QueuedSharedWorkerShutdown
    210 #endif
    211 IN_PROC_BROWSER_TEST_F(WorkerTest, MAYBE_QueuedSharedWorkerShutdown) {
    212   // Tests to make sure that queued shared workers are started up when shared
    213   // workers shut down.
    214   int max_workers_per_tab = WorkerServiceImpl::kMaxWorkersPerTabWhenSeparate;
    215   std::string query = base::StringPrintf("?count=%d", max_workers_per_tab);
    216   RunTest("queued_shared_worker_shutdown.html", query);
    217   ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab));
    218 }
    219 
    220 // Flaky, http://crbug.com/69881.
    221 // Sometimes triggers
    222 //     Check failed: message_ports_[message_port_id].queued_messages.empty().
    223 IN_PROC_BROWSER_TEST_F(WorkerTest, DISABLED_MultipleTabsQueuedSharedWorker) {
    224   // Tests to make sure that only one instance of queued shared workers are
    225   // started up even when those instances are on multiple tabs.
    226   int max_workers_per_tab = WorkerServiceImpl::kMaxWorkersPerTabWhenSeparate;
    227   std::string query = base::StringPrintf("?count=%d", max_workers_per_tab + 1);
    228   GURL url = GetTestURL("many_shared_workers.html", query);
    229   NavigateToURL(shell(), url);
    230   ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab));
    231 
    232   // Create same set of workers in new tab (leaves one worker queued from this
    233   // tab).
    234   url = GetTestURL("many_shared_workers.html", query);
    235   NavigateToURL(CreateBrowser(), url);
    236   ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab));
    237 
    238   // Now shutdown one of the shared workers - this will fire both queued
    239   // workers, but only one instance should be started.
    240   url = GetTestURL("shutdown_shared_worker.html", "?id=0");
    241   NavigateToURL(CreateBrowser(), url);
    242   ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab));
    243 }
    244 
    245 // Flaky: http://crbug.com/48148
    246 IN_PROC_BROWSER_TEST_F(WorkerTest, DISABLED_QueuedSharedWorkerStartedFromOtherTab) {
    247   // Tests to make sure that queued shared workers are started up when
    248   // an instance is launched from another tab.
    249   int max_workers_per_tab = WorkerServiceImpl::kMaxWorkersPerTabWhenSeparate;
    250   std::string query = base::StringPrintf("?count=%d", max_workers_per_tab + 1);
    251   GURL url = GetTestURL("many_shared_workers.html", query);
    252   NavigateToURL(shell(), url);
    253   ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab));
    254 
    255   // First window has hit its limit. Now launch second window which creates
    256   // the same worker that was queued in the first window, to ensure it gets
    257   // connected to the first window too.
    258   query = base::StringPrintf("?id=%d", max_workers_per_tab);
    259   url = GetTestURL("single_shared_worker.html", query);
    260   NavigateToURL(CreateBrowser(), url);
    261 
    262   ASSERT_TRUE(WaitForWorkerProcessCount(max_workers_per_tab + 1));
    263 }
    264 
    265 IN_PROC_BROWSER_TEST_F(WorkerTest, WebSocketSharedWorker) {
    266   // Launch WebSocket server.
    267   net::SpawnedTestServer ws_server(net::SpawnedTestServer::TYPE_WS,
    268                                    net::SpawnedTestServer::kLocalhost,
    269                                    net::GetWebSocketTestDataDirectory());
    270   ASSERT_TRUE(ws_server.Start());
    271 
    272   // Generate test URL.
    273   std::string scheme("http");
    274   GURL::Replacements replacements;
    275   replacements.SetSchemeStr(scheme);
    276   GURL url = ws_server.GetURL(
    277       "websocket_shared_worker.html").ReplaceComponents(replacements);
    278 
    279   // Run test.
    280   Shell* window = shell();
    281   const string16 expected_title = ASCIIToUTF16("OK");
    282   TitleWatcher title_watcher(window->web_contents(), expected_title);
    283   NavigateToURL(window, url);
    284   string16 final_title = title_watcher.WaitAndGetTitle();
    285   EXPECT_EQ(expected_title, final_title);
    286 }
    287 
    288 }  // namespace content
    289