• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2017 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4 
5 #include <list>
6 #include <map>
7 #include <memory>
8 #include <set>
9 
10 #include "include/base/cef_callback.h"
11 #include "include/base/cef_ref_counted.h"
12 #include "include/cef_command_line.h"
13 #include "include/cef_server.h"
14 #include "include/cef_task.h"
15 #include "include/cef_urlrequest.h"
16 #include "include/wrapper/cef_closure_task.h"
17 #include "tests/ceftests/routing_test_handler.h"
18 #include "tests/ceftests/test_util.h"
19 #include "tests/gtest/include/gtest/gtest.h"
20 
21 namespace {
22 
23 // Must use a different port than test_server.cc.
24 const char kTestServerAddress[] = "127.0.0.1";
25 const uint16 kTestServerPort = 8099;
26 const int kTestTimeout = 5000;
27 
GetTestServerOrigin(bool is_websocket)28 std::string GetTestServerOrigin(bool is_websocket) {
29   std::stringstream ss;
30   ss << (is_websocket ? "ws://" : "http://") << kTestServerAddress << ":"
31      << kTestServerPort;
32   return ss.str();
33 }
34 
35 // Handles the test server. Used for both HTTP and WebSocket tests.
36 class TestServerHandler : public CefServerHandler {
37  public:
38   // HTTP test handler.
39   // The methods of this class are always executed on the server thread.
40   class HttpRequestHandler {
41    public:
~HttpRequestHandler()42     virtual ~HttpRequestHandler() {}
43     virtual bool HandleRequest(CefRefPtr<CefServer> server,
44                                int connection_id,
45                                const CefString& client_address,
46                                CefRefPtr<CefRequest> request) = 0;
47     virtual bool VerifyResults() = 0;
48     virtual std::string ToString() = 0;
49   };
50 
51   // WebSocket test handler.
52   // The methods of this class are always executed on the server thread.
53   class WsRequestHandler {
54    public:
~WsRequestHandler()55     virtual ~WsRequestHandler() {}
56     virtual bool HandleRequest(CefRefPtr<CefServer> server,
57                                int connection_id,
58                                const CefString& client_address,
59                                CefRefPtr<CefRequest> request,
60                                CefRefPtr<CefCallback> callback) = 0;
61     virtual bool HandleConnected(CefRefPtr<CefServer> server,
62                                  int connection_id) = 0;
63     virtual bool HandleMessage(CefRefPtr<CefServer> server,
64                                int connection_id,
65                                const void* data,
66                                size_t data_size) = 0;
67     virtual bool VerifyResults() = 0;
68     virtual std::string ToString() = 0;
69   };
70 
71   // |start_callback| will be executed on the UI thread after the server is
72   // started.
73   // |destroy_callback| will be executed on the UI thread after this handler
74   // object is destroyed.
TestServerHandler(base::OnceClosure start_callback,base::OnceClosure destroy_callback)75   TestServerHandler(base::OnceClosure start_callback,
76                     base::OnceClosure destroy_callback)
77       : initialized_(false),
78         start_callback_(std::move(start_callback)),
79         destroy_callback_(std::move(destroy_callback)),
80         expected_connection_ct_(0),
81         actual_connection_ct_(0),
82         expected_http_request_ct_(0),
83         actual_http_request_ct_(0),
84         expected_ws_request_ct_(0),
85         actual_ws_request_ct_(0),
86         expected_ws_connected_ct_(0),
87         actual_ws_connected_ct_(0),
88         expected_ws_message_ct_(0),
89         actual_ws_message_ct_(0) {
90     EXPECT_FALSE(destroy_callback_.is_null());
91   }
92 
~TestServerHandler()93   virtual ~TestServerHandler() {
94     EXPECT_UI_THREAD();
95 
96     if (!http_request_handler_list_.empty()) {
97       HttpRequestHandlerList::const_iterator it =
98           http_request_handler_list_.begin();
99       for (; it != http_request_handler_list_.end(); ++it)
100         delete *it;
101     }
102 
103     if (!ws_request_handler_list_.empty()) {
104       WsRequestHandlerList::const_iterator it =
105           ws_request_handler_list_.begin();
106       for (; it != ws_request_handler_list_.end(); ++it)
107         delete *it;
108     }
109 
110     std::move(destroy_callback_).Run();
111   }
112 
113   // Must be called before CreateServer().
SetExpectedConnectionCount(int expected)114   void SetExpectedConnectionCount(int expected) {
115     EXPECT_FALSE(initialized_);
116     expected_connection_ct_ = expected;
117   }
118 
119   // Must be called before CreateServer().
AddHttpRequestHandler(std::unique_ptr<HttpRequestHandler> request_handler)120   void AddHttpRequestHandler(
121       std::unique_ptr<HttpRequestHandler> request_handler) {
122     EXPECT_FALSE(initialized_);
123     EXPECT_TRUE(request_handler);
124     http_request_handler_list_.push_back(request_handler.release());
125   }
126 
127   // Must be called before CreateServer().
SetExpectedHttpRequestCount(int expected)128   void SetExpectedHttpRequestCount(int expected) {
129     EXPECT_FALSE(initialized_);
130     expected_http_request_ct_ = expected;
131   }
132 
133   // Must be called before CreateServer().
AddWsRequestHandler(std::unique_ptr<WsRequestHandler> request_handler)134   void AddWsRequestHandler(std::unique_ptr<WsRequestHandler> request_handler) {
135     EXPECT_FALSE(initialized_);
136     EXPECT_TRUE(request_handler);
137     ws_request_handler_list_.push_back(request_handler.release());
138   }
139 
140   // Must be called before CreateServer().
SetExpectedWsRequestCount(int expected)141   void SetExpectedWsRequestCount(int expected) {
142     EXPECT_FALSE(initialized_);
143     expected_ws_request_ct_ = expected;
144   }
145 
146   // Must be called before CreateServer().
SetExpectedWsConnectedCount(int expected)147   void SetExpectedWsConnectedCount(int expected) {
148     EXPECT_FALSE(initialized_);
149     expected_ws_connected_ct_ = expected;
150   }
151 
152   // Must be called before CreateServer().
SetExpectedWsMessageCount(int expected)153   void SetExpectedWsMessageCount(int expected) {
154     EXPECT_FALSE(initialized_);
155     expected_ws_message_ct_ = expected;
156   }
157 
CreateServer()158   void CreateServer() {
159     EXPECT_FALSE(initialized_);
160     initialized_ = true;
161     CefServer::CreateServer(kTestServerAddress, kTestServerPort, 10, this);
162   }
163 
164   // Results in a call to VerifyResults() and eventual execution of the
165   // |destroy_callback|.
ShutdownServer()166   void ShutdownServer() {
167     EXPECT_TRUE(server_);
168     if (server_)
169       server_->Shutdown();
170   }
171 
OnServerCreated(CefRefPtr<CefServer> server)172   void OnServerCreated(CefRefPtr<CefServer> server) override {
173     EXPECT_TRUE(server);
174     EXPECT_TRUE(server->IsRunning());
175     EXPECT_FALSE(server->HasConnection());
176 
177     EXPECT_FALSE(got_server_created_);
178     got_server_created_.yes();
179 
180     EXPECT_FALSE(server_);
181     server_ = server;
182 
183     EXPECT_FALSE(server_runner_);
184     server_runner_ = server_->GetTaskRunner();
185     EXPECT_TRUE(server_runner_);
186     EXPECT_TRUE(server_runner_->BelongsToCurrentThread());
187 
188     RunStartCallback();
189   }
190 
OnServerDestroyed(CefRefPtr<CefServer> server)191   void OnServerDestroyed(CefRefPtr<CefServer> server) override {
192     EXPECT_TRUE(VerifyServer(server));
193     EXPECT_FALSE(server->IsRunning());
194     EXPECT_FALSE(server->HasConnection());
195 
196     EXPECT_FALSE(got_server_destroyed_);
197     got_server_destroyed_.yes();
198 
199     server_ = nullptr;
200 
201     VerifyResults();
202   }
203 
OnClientConnected(CefRefPtr<CefServer> server,int connection_id)204   void OnClientConnected(CefRefPtr<CefServer> server,
205                          int connection_id) override {
206     EXPECT_TRUE(VerifyServer(server));
207     EXPECT_TRUE(server->HasConnection());
208     EXPECT_TRUE(server->IsValidConnection(connection_id));
209 
210     EXPECT_TRUE(connection_id_set_.find(connection_id) ==
211                 connection_id_set_.end());
212     connection_id_set_.insert(connection_id);
213 
214     actual_connection_ct_++;
215   }
216 
OnClientDisconnected(CefRefPtr<CefServer> server,int connection_id)217   void OnClientDisconnected(CefRefPtr<CefServer> server,
218                             int connection_id) override {
219     EXPECT_TRUE(VerifyServer(server));
220     EXPECT_FALSE(server->IsValidConnection(connection_id));
221 
222     ConnectionIdSet::iterator it = connection_id_set_.find(connection_id);
223     EXPECT_TRUE(it != connection_id_set_.end());
224     connection_id_set_.erase(it);
225 
226     ConnectionIdSet::iterator it2 = ws_connection_id_set_.find(connection_id);
227     if (it2 != ws_connection_id_set_.end())
228       ws_connection_id_set_.erase(it2);
229 
230     if (connection_id_set_.empty()) {
231       EXPECT_TRUE(ws_connection_id_set_.empty());
232       EXPECT_FALSE(server->HasConnection());
233     }
234   }
235 
OnHttpRequest(CefRefPtr<CefServer> server,int connection_id,const CefString & client_address,CefRefPtr<CefRequest> request)236   void OnHttpRequest(CefRefPtr<CefServer> server,
237                      int connection_id,
238                      const CefString& client_address,
239                      CefRefPtr<CefRequest> request) override {
240     EXPECT_TRUE(VerifyServer(server));
241     EXPECT_TRUE(VerifyConnection(connection_id));
242     EXPECT_FALSE(client_address.empty());
243     EXPECT_TRUE(VerifyRequest(request, false));
244 
245     bool handled = false;
246     HttpRequestHandlerList::const_iterator it =
247         http_request_handler_list_.begin();
248     for (; it != http_request_handler_list_.end(); ++it) {
249       handled =
250           (*it)->HandleRequest(server, connection_id, client_address, request);
251       if (handled)
252         break;
253     }
254     EXPECT_TRUE(handled) << "missing HttpRequestHandler for "
255                          << request->GetURL().ToString();
256 
257     actual_http_request_ct_++;
258   }
259 
OnWebSocketRequest(CefRefPtr<CefServer> server,int connection_id,const CefString & client_address,CefRefPtr<CefRequest> request,CefRefPtr<CefCallback> callback)260   void OnWebSocketRequest(CefRefPtr<CefServer> server,
261                           int connection_id,
262                           const CefString& client_address,
263                           CefRefPtr<CefRequest> request,
264                           CefRefPtr<CefCallback> callback) override {
265     EXPECT_TRUE(VerifyServer(server));
266     EXPECT_TRUE(VerifyConnection(connection_id));
267     EXPECT_FALSE(client_address.empty());
268     EXPECT_TRUE(VerifyRequest(request, true));
269 
270     EXPECT_TRUE(ws_connection_id_set_.find(connection_id) ==
271                 ws_connection_id_set_.end());
272     ws_connection_id_set_.insert(connection_id);
273 
274     bool handled = false;
275     WsRequestHandlerList::const_iterator it = ws_request_handler_list_.begin();
276     for (; it != ws_request_handler_list_.end(); ++it) {
277       handled = (*it)->HandleRequest(server, connection_id, client_address,
278                                      request, callback);
279       if (handled)
280         break;
281     }
282     EXPECT_TRUE(handled) << "missing WsRequestHandler for "
283                          << request->GetURL().ToString();
284 
285     actual_ws_request_ct_++;
286   }
287 
OnWebSocketConnected(CefRefPtr<CefServer> server,int connection_id)288   void OnWebSocketConnected(CefRefPtr<CefServer> server,
289                             int connection_id) override {
290     EXPECT_TRUE(VerifyServer(server));
291     EXPECT_TRUE(VerifyConnection(connection_id));
292 
293     EXPECT_TRUE(ws_connection_id_set_.find(connection_id) !=
294                 ws_connection_id_set_.end());
295 
296     bool handled = false;
297     WsRequestHandlerList::const_iterator it = ws_request_handler_list_.begin();
298     for (; it != ws_request_handler_list_.end(); ++it) {
299       handled = (*it)->HandleConnected(server, connection_id);
300       if (handled)
301         break;
302     }
303     EXPECT_TRUE(handled) << "missing WsRequestHandler for " << connection_id;
304 
305     actual_ws_connected_ct_++;
306   }
307 
OnWebSocketMessage(CefRefPtr<CefServer> server,int connection_id,const void * data,size_t data_size)308   void OnWebSocketMessage(CefRefPtr<CefServer> server,
309                           int connection_id,
310                           const void* data,
311                           size_t data_size) override {
312     EXPECT_TRUE(VerifyServer(server));
313     EXPECT_TRUE(VerifyConnection(connection_id));
314     EXPECT_TRUE(data);
315     EXPECT_GT(data_size, 0U);
316 
317     EXPECT_TRUE(ws_connection_id_set_.find(connection_id) !=
318                 ws_connection_id_set_.end());
319 
320     bool handled = false;
321     WsRequestHandlerList::const_iterator it = ws_request_handler_list_.begin();
322     for (; it != ws_request_handler_list_.end(); ++it) {
323       handled = (*it)->HandleMessage(server, connection_id, data, data_size);
324       if (handled)
325         break;
326     }
327     EXPECT_TRUE(handled) << "missing WsRequestHandler for " << connection_id;
328 
329     actual_ws_message_ct_++;
330   }
331 
332  private:
RunningOnServerThread()333   bool RunningOnServerThread() {
334     return server_runner_ && server_runner_->BelongsToCurrentThread();
335   }
336 
VerifyServer(CefRefPtr<CefServer> server)337   bool VerifyServer(CefRefPtr<CefServer> server) {
338     V_DECLARE();
339     V_EXPECT_TRUE(RunningOnServerThread());
340     V_EXPECT_TRUE(server);
341     V_EXPECT_TRUE(server_);
342     V_EXPECT_TRUE(server->GetAddress().ToString() ==
343                   server_->GetAddress().ToString());
344     V_RETURN();
345   }
346 
VerifyConnection(int connection_id)347   bool VerifyConnection(int connection_id) {
348     return connection_id_set_.find(connection_id) != connection_id_set_.end();
349   }
350 
VerifyRequest(CefRefPtr<CefRequest> request,bool is_websocket)351   bool VerifyRequest(CefRefPtr<CefRequest> request, bool is_websocket) {
352     V_DECLARE();
353 
354     V_EXPECT_FALSE(request->GetMethod().empty());
355 
356     const std::string& url = request->GetURL();
357     V_EXPECT_FALSE(url.empty());
358     const std::string& address = server_->GetAddress();
359     V_EXPECT_TRUE(url.find((is_websocket ? "ws://" : "http://") + address) == 0)
360         << "url " << url << " address " << address;
361 
362     CefRefPtr<CefPostData> post_data = request->GetPostData();
363     if (post_data) {
364       CefPostData::ElementVector elements;
365       post_data->GetElements(elements);
366       V_EXPECT_TRUE(elements.size() == 1);
367       V_EXPECT_TRUE(elements[0]->GetBytesCount() > 0U);
368     }
369 
370     V_RETURN();
371   }
372 
VerifyResults()373   void VerifyResults() {
374     EXPECT_TRUE(RunningOnServerThread());
375 
376     EXPECT_TRUE(got_server_created_);
377     EXPECT_TRUE(got_server_destroyed_);
378     EXPECT_TRUE(connection_id_set_.empty());
379     EXPECT_EQ(expected_connection_ct_, actual_connection_ct_);
380 
381     // HTTP
382 
383     EXPECT_EQ(expected_http_request_ct_, actual_http_request_ct_);
384 
385     if (!http_request_handler_list_.empty()) {
386       HttpRequestHandlerList::const_iterator it =
387           http_request_handler_list_.begin();
388       for (; it != http_request_handler_list_.end(); ++it) {
389         EXPECT_TRUE((*it)->VerifyResults())
390             << "HttpRequestHandler for " << (*it)->ToString();
391       }
392     }
393 
394     // WebSocket
395 
396     EXPECT_EQ(expected_ws_request_ct_, actual_ws_request_ct_);
397     EXPECT_EQ(expected_ws_connected_ct_, actual_ws_connected_ct_);
398     EXPECT_EQ(expected_ws_message_ct_, actual_ws_message_ct_);
399 
400     if (!ws_request_handler_list_.empty()) {
401       WsRequestHandlerList::const_iterator it =
402           ws_request_handler_list_.begin();
403       for (; it != ws_request_handler_list_.end(); ++it) {
404         EXPECT_TRUE((*it)->VerifyResults())
405             << "WsRequestHandler for " << (*it)->ToString();
406       }
407     }
408   }
409 
410  private:
RunStartCallback()411   void RunStartCallback() {
412     if (!CefCurrentlyOn(TID_UI)) {
413       CefPostTask(TID_UI,
414                   base::BindOnce(&TestServerHandler::RunStartCallback, this));
415       return;
416     }
417 
418     EXPECT_FALSE(start_callback_.is_null());
419     std::move(start_callback_).Run();
420   }
421 
422   CefRefPtr<CefServer> server_;
423   CefRefPtr<CefTaskRunner> server_runner_;
424   bool initialized_;
425 
426   // After initialization only accessed on the UI thread.
427   base::OnceClosure start_callback_;
428   base::OnceClosure destroy_callback_;
429 
430   // After initialization the below members are only accessed on the server
431   // thread.
432 
433   TrackCallback got_server_created_;
434   TrackCallback got_server_destroyed_;
435 
436   typedef std::set<int> ConnectionIdSet;
437   ConnectionIdSet connection_id_set_;
438 
439   int expected_connection_ct_;
440   int actual_connection_ct_;
441 
442   // HTTP
443 
444   typedef std::list<HttpRequestHandler*> HttpRequestHandlerList;
445   HttpRequestHandlerList http_request_handler_list_;
446 
447   int expected_http_request_ct_;
448   int actual_http_request_ct_;
449 
450   // WebSocket
451 
452   typedef std::list<WsRequestHandler*> WsRequestHandlerList;
453   WsRequestHandlerList ws_request_handler_list_;
454 
455   ConnectionIdSet ws_connection_id_set_;
456 
457   int expected_ws_request_ct_;
458   int actual_ws_request_ct_;
459 
460   int expected_ws_connected_ct_;
461   int actual_ws_connected_ct_;
462 
463   int expected_ws_message_ct_;
464   int actual_ws_message_ct_;
465 
466   IMPLEMENT_REFCOUNTING(TestServerHandler);
467   DISALLOW_COPY_AND_ASSIGN(TestServerHandler);
468 };
469 
470 // HTTP TESTS
471 
472 // Test runner for 1 or more HTTP requests/responses.
473 // Works similarly to TestHandler but without the CefClient dependencies.
474 class HttpTestRunner : public base::RefCountedThreadSafe<HttpTestRunner> {
475  public:
476   // The methods of this class are always executed on the UI thread.
477   class RequestRunner {
478    public:
~RequestRunner()479     virtual ~RequestRunner() {}
480 
481     // Create the server-side handler for the request.
482     virtual std::unique_ptr<TestServerHandler::HttpRequestHandler>
483     CreateHttpRequestHandler() = 0;
484 
485     // Run the request and execute |complete_callback| on completion.
486     virtual void RunRequest(base::OnceClosure complete_callback) = 0;
487 
488     virtual bool VerifyResults() = 0;
489     virtual std::string ToString() = 0;
490   };
491 
492   // If |parallel_requests| is true all requests will be run at the same time,
493   // otherwise one request will be run at a time.
HttpTestRunner(bool parallel_requests)494   HttpTestRunner(bool parallel_requests)
495       : parallel_requests_(parallel_requests),
496         initialized_(false),
497         next_request_id_(0) {}
498 
~HttpTestRunner()499   virtual ~HttpTestRunner() {
500     if (destroy_event_)
501       destroy_event_->Signal();
502   }
503 
AddRequestRunner(std::unique_ptr<RequestRunner> request_runner)504   void AddRequestRunner(std::unique_ptr<RequestRunner> request_runner) {
505     EXPECT_FALSE(initialized_);
506     request_runner_map_.insert(
507         std::make_pair(++next_request_id_, request_runner.release()));
508   }
509 
510   // Blocks until the test has completed or timed out.
ExecuteTest()511   void ExecuteTest() {
512     EXPECT_FALSE(CefCurrentlyOn(TID_UI));
513 
514     handler_ = new TestServerHandler(
515         base::BindOnce(&HttpTestRunner::OnServerStarted, this),
516         base::BindOnce(&HttpTestRunner::OnServerDestroyed, this));
517 
518     run_event_ = CefWaitableEvent::CreateWaitableEvent(false, false);
519 
520     CefPostTask(TID_UI, base::BindOnce(&HttpTestRunner::RunTest, this));
521 
522     // Block until test completion.
523     run_event_->Wait();
524   }
525 
526   // Event that will be signaled from the HttpTestRunner destructor.
527   // Used by ReleaseAndWaitForDestructor.
SetDestroyEvent(CefRefPtr<CefWaitableEvent> event)528   void SetDestroyEvent(CefRefPtr<CefWaitableEvent> event) {
529     destroy_event_ = event;
530   }
531 
532  private:
RunTest()533   void RunTest() {
534     EXPECT_UI_THREAD();
535     EXPECT_FALSE(initialized_);
536     initialized_ = true;
537 
538     EXPECT_FALSE(request_runner_map_.empty());
539     RequestRunnerMap::const_iterator it = request_runner_map_.begin();
540     for (; it != request_runner_map_.end(); ++it) {
541       handler_->AddHttpRequestHandler(it->second->CreateHttpRequestHandler());
542     }
543 
544     handler_->SetExpectedConnectionCount(
545         static_cast<int>(request_runner_map_.size()));
546     handler_->SetExpectedHttpRequestCount(
547         static_cast<int>(request_runner_map_.size()));
548 
549     handler_->CreateServer();
550 
551     SetTestTimeout(kTestTimeout);
552   }
553 
OnServerStarted()554   void OnServerStarted() {
555     EXPECT_UI_THREAD();
556     if (parallel_requests_) {
557       RunAllRequests();
558     } else {
559       RunNextRequest();
560     }
561   }
562 
OnServerDestroyed()563   void OnServerDestroyed() {
564     EXPECT_UI_THREAD();
565     EXPECT_FALSE(got_server_destroyed_);
566     got_server_destroyed_.yes();
567 
568     // Allow the call stack to unwind.
569     CefPostTask(TID_UI, base::BindOnce(&HttpTestRunner::DestroyTest, this));
570   }
571 
572   // Run all requests in parallel.
RunAllRequests()573   void RunAllRequests() {
574     RequestRunnerMap::const_iterator it = request_runner_map_.begin();
575     for (; it != request_runner_map_.end(); ++it) {
576       it->second->RunRequest(
577           base::BindOnce(&HttpTestRunner::OnRequestComplete, this, it->first));
578     }
579   }
580 
581   // Run one request at a time.
RunNextRequest()582   void RunNextRequest() {
583     RequestRunnerMap::const_iterator it = request_runner_map_.begin();
584     it->second->RunRequest(
585         base::BindOnce(&HttpTestRunner::OnRequestComplete, this, it->first));
586   }
587 
OnRequestComplete(int request_id)588   void OnRequestComplete(int request_id) {
589     EXPECT_UI_THREAD()
590     // Allow the call stack to unwind.
591     CefPostTask(TID_UI,
592                 base::BindOnce(&HttpTestRunner::OnRequestCompleteContinue, this,
593                                request_id));
594   }
595 
OnRequestCompleteContinue(int request_id)596   void OnRequestCompleteContinue(int request_id) {
597     RequestRunnerMap::iterator it = request_runner_map_.find(request_id);
598     EXPECT_TRUE(it != request_runner_map_.end());
599 
600     // Verify the request results.
601     EXPECT_TRUE(it->second->VerifyResults())
602         << "request_id " << request_id << " RequestRunner for "
603         << it->second->ToString();
604     delete it->second;
605     request_runner_map_.erase(it);
606 
607     if (request_runner_map_.empty()) {
608       got_all_requests_.yes();
609 
610       // Will trigger TestServerHandler::HttpRequestHandler verification and a
611       // call to OnServerDestroyed().
612       handler_->ShutdownServer();
613       handler_ = nullptr;
614     } else if (!parallel_requests_) {
615       RunNextRequest();
616     }
617   }
618 
DestroyTest()619   void DestroyTest() {
620     EXPECT_UI_THREAD();
621 
622     EXPECT_TRUE(got_all_requests_);
623     EXPECT_TRUE(got_server_destroyed_);
624     EXPECT_TRUE(request_runner_map_.empty());
625 
626     // Cancel the timeout, if any.
627     if (ui_thread_helper_)
628       ui_thread_helper_.reset();
629 
630     // Signal test completion.
631     run_event_->Signal();
632   }
633 
GetUIThreadHelper()634   TestHandler::UIThreadHelper* GetUIThreadHelper() {
635     EXPECT_UI_THREAD();
636     if (!ui_thread_helper_)
637       ui_thread_helper_.reset(new TestHandler::UIThreadHelper());
638     return ui_thread_helper_.get();
639   }
640 
SetTestTimeout(int timeout_ms)641   void SetTestTimeout(int timeout_ms) {
642     EXPECT_UI_THREAD();
643     if (CefCommandLine::GetGlobalCommandLine()->HasSwitch(
644             "disable-test-timeout")) {
645       return;
646     }
647 
648     // Use a weak reference to |this| via UIThreadHelper so that the
649     // test runner can be destroyed before the timeout expires.
650     GetUIThreadHelper()->PostDelayedTask(
651         base::BindOnce(&HttpTestRunner::OnTestTimeout, base::Unretained(this),
652                        timeout_ms),
653         timeout_ms);
654   }
655 
OnTestTimeout(int timeout_ms)656   void OnTestTimeout(int timeout_ms) {
657     EXPECT_UI_THREAD();
658     EXPECT_TRUE(false) << "Test timed out after " << timeout_ms << "ms";
659     DestroyTest();
660   }
661 
662   bool parallel_requests_;
663   CefRefPtr<CefWaitableEvent> run_event_;
664   CefRefPtr<CefWaitableEvent> destroy_event_;
665   CefRefPtr<TestServerHandler> handler_;
666   bool initialized_;
667 
668   // After initialization the below members are only accessed on the UI thread.
669 
670   int next_request_id_;
671 
672   // Map of request ID to RequestRunner.
673   typedef std::map<int, RequestRunner*> RequestRunnerMap;
674   RequestRunnerMap request_runner_map_;
675 
676   TrackCallback got_all_requests_;
677   TrackCallback got_server_destroyed_;
678 
679   std::unique_ptr<TestHandler::UIThreadHelper> ui_thread_helper_;
680 
681   DISALLOW_COPY_AND_ASSIGN(HttpTestRunner);
682 };
683 
684 // Structure representing the data that can be sent via
685 // CefServer::SendHttp*Response().
686 struct HttpServerResponse {
687   enum Type { TYPE_200, TYPE_404, TYPE_500, TYPE_CUSTOM };
688 
HttpServerResponse__anond34723fb0111::HttpServerResponse689   explicit HttpServerResponse(Type response_type)
690       : type(response_type), no_content_length(false) {}
691 
692   Type type;
693 
694   // Used with 200 and CUSTOM response type.
695   std::string content;
696   std::string content_type;
697 
698   // Used with 500 response type.
699   std::string error_message;
700 
701   // Used with CUSTOM response type.
702   int response_code;
703   CefServer::HeaderMap extra_headers;
704   bool no_content_length;
705 };
706 
SendHttpServerResponse(CefRefPtr<CefServer> server,int connection_id,const HttpServerResponse & response)707 void SendHttpServerResponse(CefRefPtr<CefServer> server,
708                             int connection_id,
709                             const HttpServerResponse& response) {
710   EXPECT_TRUE(server->GetTaskRunner()->BelongsToCurrentThread());
711   EXPECT_TRUE(server->IsValidConnection(connection_id));
712 
713   switch (response.type) {
714     case HttpServerResponse::TYPE_200:
715       EXPECT_TRUE(!response.content_type.empty());
716       server->SendHttp200Response(connection_id, response.content_type,
717                                   response.content.data(),
718                                   response.content.size());
719       break;
720     case HttpServerResponse::TYPE_404:
721       server->SendHttp404Response(connection_id);
722       break;
723     case HttpServerResponse::TYPE_500:
724       server->SendHttp500Response(connection_id, response.error_message);
725       break;
726     case HttpServerResponse::TYPE_CUSTOM:
727       EXPECT_TRUE(!response.content_type.empty());
728       server->SendHttpResponse(
729           connection_id, response.response_code, response.content_type,
730           response.no_content_length
731               ? -1
732               : static_cast<int64>(response.content.size()),
733           response.extra_headers);
734       if (!response.content.empty()) {
735         server->SendRawData(connection_id, response.content.data(),
736                             response.content.size());
737       }
738       if (!response.content.empty() ||
739           (response.content.empty() && response.no_content_length)) {
740         server->CloseConnection(connection_id);
741       }
742       break;
743   }
744 
745   // All of the above responses should close the connection.
746   EXPECT_FALSE(server->IsValidConnection(connection_id));
747 }
748 
GetHeaderValue(const CefServer::HeaderMap & header_map,const std::string & header_name)749 std::string GetHeaderValue(const CefServer::HeaderMap& header_map,
750                            const std::string& header_name) {
751   CefServer::HeaderMap::const_iterator it = header_map.find(header_name);
752   if (it != header_map.end())
753     return it->second;
754   return std::string();
755 }
756 
VerifyHttpServerResponse(const HttpServerResponse & expected_response,CefRefPtr<CefResponse> response,const std::string & data)757 void VerifyHttpServerResponse(const HttpServerResponse& expected_response,
758                               CefRefPtr<CefResponse> response,
759                               const std::string& data) {
760   CefServer::HeaderMap header_map;
761   response->GetHeaderMap(header_map);
762 
763   switch (expected_response.type) {
764     case HttpServerResponse::TYPE_200:
765       EXPECT_EQ(200, response->GetStatus());
766       EXPECT_STREQ(expected_response.content_type.c_str(),
767                    GetHeaderValue(header_map, "Content-Type").c_str());
768       EXPECT_STREQ(expected_response.content.c_str(), data.c_str());
769       break;
770     case HttpServerResponse::TYPE_404:
771       EXPECT_EQ(404, response->GetStatus());
772       break;
773     case HttpServerResponse::TYPE_500:
774       EXPECT_EQ(500, response->GetStatus());
775       break;
776     case HttpServerResponse::TYPE_CUSTOM:
777       EXPECT_EQ(expected_response.response_code, response->GetStatus());
778       EXPECT_STREQ(expected_response.content_type.c_str(),
779                    GetHeaderValue(header_map, "Content-Type").c_str());
780       if (expected_response.no_content_length) {
781         EXPECT_TRUE(GetHeaderValue(header_map, "Content-Length").empty());
782       } else {
783         EXPECT_FALSE(GetHeaderValue(header_map, "Content-Length").empty());
784       }
785       EXPECT_STREQ(expected_response.content.c_str(), data.c_str());
786       TestMapEqual(expected_response.extra_headers, header_map, true);
787       break;
788   }
789 }
790 
CreateTestServerRequest(const std::string & path,const std::string & method,const std::string & data=std::string (),const std::string & content_type=std::string (),const CefRequest::HeaderMap & extra_headers=CefRequest::HeaderMap ())791 CefRefPtr<CefRequest> CreateTestServerRequest(
792     const std::string& path,
793     const std::string& method,
794     const std::string& data = std::string(),
795     const std::string& content_type = std::string(),
796     const CefRequest::HeaderMap& extra_headers = CefRequest::HeaderMap()) {
797   CefRefPtr<CefRequest> request = CefRequest::Create();
798   request->SetURL(GetTestServerOrigin(false) + "/" + path);
799   request->SetMethod(method);
800 
801   CefRequest::HeaderMap header_map;
802 
803   if (!data.empty()) {
804     CefRefPtr<CefPostData> post_data = CefPostData::Create();
805     CefRefPtr<CefPostDataElement> post_element = CefPostDataElement::Create();
806     post_element->SetToBytes(data.size(), data.data());
807     post_data->AddElement(post_element);
808     request->SetPostData(post_data);
809 
810     EXPECT_FALSE(content_type.empty());
811     header_map.insert(std::make_pair("content-type", content_type));
812   }
813 
814   if (!extra_headers.empty())
815     header_map.insert(extra_headers.begin(), extra_headers.end());
816   request->SetHeaderMap(header_map);
817 
818   return request;
819 }
820 
821 // RequestHandler that returns a static response for 1 or more requests.
822 class StaticHttpServerRequestHandler
823     : public TestServerHandler::HttpRequestHandler {
824  public:
StaticHttpServerRequestHandler(CefRefPtr<CefRequest> expected_request,int expected_request_ct,const HttpServerResponse & response)825   StaticHttpServerRequestHandler(CefRefPtr<CefRequest> expected_request,
826                                  int expected_request_ct,
827                                  const HttpServerResponse& response)
828       : expected_request_(expected_request),
829         expected_request_ct_(expected_request_ct),
830         actual_request_ct_(0),
831         response_(response) {}
832 
HandleRequest(CefRefPtr<CefServer> server,int connection_id,const CefString & client_address,CefRefPtr<CefRequest> request)833   bool HandleRequest(CefRefPtr<CefServer> server,
834                      int connection_id,
835                      const CefString& client_address,
836                      CefRefPtr<CefRequest> request) override {
837     if (request->GetURL() == expected_request_->GetURL() &&
838         request->GetMethod() == expected_request_->GetMethod()) {
839       TestRequestEqual(expected_request_, request, true);
840       actual_request_ct_++;
841 
842       SendHttpServerResponse(server, connection_id, response_);
843       return true;
844     }
845 
846     return false;
847   }
848 
VerifyResults()849   bool VerifyResults() override {
850     EXPECT_EQ(expected_request_ct_, actual_request_ct_);
851     return expected_request_ct_ == actual_request_ct_;
852   }
853 
ToString()854   std::string ToString() override { return expected_request_->GetURL(); }
855 
856  private:
857   CefRefPtr<CefRequest> expected_request_;
858   int expected_request_ct_;
859   int actual_request_ct_;
860   HttpServerResponse response_;
861 
862   DISALLOW_COPY_AND_ASSIGN(StaticHttpServerRequestHandler);
863 };
864 
865 // URLRequestClient that runs a single request and executes a callback with the
866 // response.
867 class StaticHttpURLRequestClient : public CefURLRequestClient {
868  public:
869   using ResponseCallback =
870       base::OnceCallback<void(cef_errorcode_t /* error */,
871                               CefRefPtr<CefResponse> /* response */,
872                               const std::string& /* data */)>;
873 
874   // |response_callback| will be executed on the UI thread when the response
875   // is complete.
StaticHttpURLRequestClient(CefRefPtr<CefRequest> request,ResponseCallback response_callback)876   StaticHttpURLRequestClient(CefRefPtr<CefRequest> request,
877                              ResponseCallback response_callback)
878       : request_(request), response_callback_(std::move(response_callback)) {
879     EXPECT_TRUE(request_);
880     EXPECT_FALSE(response_callback_.is_null());
881   }
882 
RunRequest()883   void RunRequest() {
884     EXPECT_UI_THREAD();
885     CefURLRequest::Create(request_, this, nullptr);
886   }
887 
OnRequestComplete(CefRefPtr<CefURLRequest> request)888   void OnRequestComplete(CefRefPtr<CefURLRequest> request) override {
889     EXPECT_FALSE(response_callback_.is_null());
890     std::move(response_callback_)
891         .Run(request->GetRequestError(), request->GetResponse(), data_);
892   }
893 
OnUploadProgress(CefRefPtr<CefURLRequest> request,int64 current,int64 total)894   void OnUploadProgress(CefRefPtr<CefURLRequest> request,
895                         int64 current,
896                         int64 total) override {}
897 
OnDownloadProgress(CefRefPtr<CefURLRequest> request,int64 current,int64 total)898   void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
899                           int64 current,
900                           int64 total) override {}
901 
OnDownloadData(CefRefPtr<CefURLRequest> request,const void * data,size_t data_length)902   void OnDownloadData(CefRefPtr<CefURLRequest> request,
903                       const void* data,
904                       size_t data_length) override {
905     data_.append(static_cast<const char*>(data), data_length);
906   }
907 
GetAuthCredentials(bool isProxy,const CefString & host,int port,const CefString & realm,const CefString & scheme,CefRefPtr<CefAuthCallback> callback)908   bool GetAuthCredentials(bool isProxy,
909                           const CefString& host,
910                           int port,
911                           const CefString& realm,
912                           const CefString& scheme,
913                           CefRefPtr<CefAuthCallback> callback) override {
914     return false;
915   }
916 
917  private:
918   CefRefPtr<CefRequest> request_;
919   ResponseCallback response_callback_;
920   std::string data_;
921 
922   IMPLEMENT_REFCOUNTING(StaticHttpURLRequestClient);
923   DISALLOW_COPY_AND_ASSIGN(StaticHttpURLRequestClient);
924 };
925 
926 // RequestRunner that will manage a single static HTTP request/response.
927 class StaticHttpRequestRunner : public HttpTestRunner::RequestRunner {
928  public:
StaticHttpRequestRunner(CefRefPtr<CefRequest> request,const HttpServerResponse & response)929   StaticHttpRequestRunner(CefRefPtr<CefRequest> request,
930                           const HttpServerResponse& response)
931       : request_(request), response_(response) {}
932 
Create200(const std::string & path,bool with_content=true)933   static std::unique_ptr<HttpTestRunner::RequestRunner> Create200(
934       const std::string& path,
935       bool with_content = true) {
936     CefRefPtr<CefRequest> request = CreateTestServerRequest(path, "GET");
937     HttpServerResponse response(HttpServerResponse::TYPE_200);
938     response.content_type = "text/html";
939     if (with_content)
940       response.content = "<html>200 response content</html>";
941     return std::make_unique<StaticHttpRequestRunner>(request, response);
942   }
943 
Create404(const std::string & path)944   static std::unique_ptr<HttpTestRunner::RequestRunner> Create404(
945       const std::string& path) {
946     CefRefPtr<CefRequest> request = CreateTestServerRequest(path, "GET");
947     HttpServerResponse response(HttpServerResponse::TYPE_404);
948     return std::make_unique<StaticHttpRequestRunner>(request, response);
949   }
950 
Create500(const std::string & path)951   static std::unique_ptr<HttpTestRunner::RequestRunner> Create500(
952       const std::string& path) {
953     CefRefPtr<CefRequest> request = CreateTestServerRequest(path, "GET");
954     // Don't retry the request.
955     request->SetFlags(UR_FLAG_NO_RETRY_ON_5XX);
956     HttpServerResponse response(HttpServerResponse::TYPE_500);
957     response.error_message = "Something went wrong!";
958     return std::make_unique<StaticHttpRequestRunner>(request, response);
959   }
960 
CreateCustom(const std::string & path,bool with_content=true,bool with_content_length=true)961   static std::unique_ptr<HttpTestRunner::RequestRunner> CreateCustom(
962       const std::string& path,
963       bool with_content = true,
964       bool with_content_length = true) {
965     CefRequest::HeaderMap request_headers;
966     request_headers.insert(std::make_pair("x-request-custom1", "My Value A"));
967     request_headers.insert(std::make_pair("x-request-custom2", "My Value B"));
968     CefRefPtr<CefRequest> request = CreateTestServerRequest(
969         path, "POST", "foo=bar&choo=too", "application/x-www-form-urlencoded",
970         request_headers);
971     request->SetReferrer("http://tests/referer.html", REFERRER_POLICY_DEFAULT);
972 
973     HttpServerResponse response(HttpServerResponse::TYPE_CUSTOM);
974     response.response_code = 202;
975     if (with_content)
976       response.content = "BlahBlahBlah";
977     if (!with_content_length)
978       response.no_content_length = true;
979     response.content_type = "application/x-blah-blah";
980     response.extra_headers.insert(
981         std::make_pair("x-response-custom1", "My Value 1"));
982     response.extra_headers.insert(
983         std::make_pair("x-response-custom2", "My Value 2"));
984 
985     return std::make_unique<StaticHttpRequestRunner>(request, response);
986   }
987 
988   std::unique_ptr<TestServerHandler::HttpRequestHandler>
CreateHttpRequestHandler()989   CreateHttpRequestHandler() override {
990     EXPECT_FALSE(got_create_handler_);
991     got_create_handler_.yes();
992     return std::make_unique<StaticHttpServerRequestHandler>(request_, 1,
993                                                             response_);
994   }
995 
RunRequest(base::OnceClosure complete_callback)996   void RunRequest(base::OnceClosure complete_callback) override {
997     EXPECT_UI_THREAD();
998 
999     EXPECT_FALSE(got_run_request_);
1000     got_run_request_.yes();
1001 
1002     complete_callback_ = std::move(complete_callback);
1003 
1004     request_client_ = new StaticHttpURLRequestClient(
1005         request_, base::BindOnce(&StaticHttpRequestRunner::OnResponseComplete,
1006                                  base::Unretained(this)));
1007     request_client_->RunRequest();
1008   }
1009 
VerifyResults()1010   bool VerifyResults() override {
1011     V_DECLARE();
1012     V_EXPECT_TRUE(got_create_handler_);
1013     V_EXPECT_TRUE(got_run_request_);
1014     V_EXPECT_TRUE(got_response_complete_);
1015     V_RETURN();
1016   }
1017 
ToString()1018   std::string ToString() override { return request_->GetURL(); }
1019 
1020  private:
OnResponseComplete(cef_errorcode_t error,CefRefPtr<CefResponse> response,const std::string & data)1021   void OnResponseComplete(cef_errorcode_t error,
1022                           CefRefPtr<CefResponse> response,
1023                           const std::string& data) {
1024     EXPECT_UI_THREAD();
1025 
1026     EXPECT_FALSE(got_response_complete_);
1027     got_response_complete_.yes();
1028 
1029     EXPECT_EQ(error, ERR_NONE)
1030         << "OnResponseComplete for " << request_->GetURL().ToString();
1031     if (error == ERR_NONE)
1032       VerifyHttpServerResponse(response_, response, data);
1033 
1034     std::move(complete_callback_).Run();
1035   }
1036 
1037   CefRefPtr<CefRequest> request_;
1038   HttpServerResponse response_;
1039 
1040   CefRefPtr<StaticHttpURLRequestClient> request_client_;
1041   base::OnceClosure complete_callback_;
1042 
1043   TrackCallback got_run_request_;
1044   TrackCallback got_create_handler_;
1045   TrackCallback got_response_complete_;
1046 
1047   DISALLOW_COPY_AND_ASSIGN(StaticHttpRequestRunner);
1048 };
1049 
1050 }  // namespace
1051 
1052 // Verify handling of a single HTTP 200 request.
TEST(ServerTest,HttpSingle200)1053 TEST(ServerTest, HttpSingle200) {
1054   CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
1055   runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200.html"));
1056   runner->ExecuteTest();
1057   ReleaseAndWaitForDestructor(runner);
1058 }
1059 
1060 // Verify handling of a single HTTP 200 request with no content.
TEST(ServerTest,HttpSingle200NoContent)1061 TEST(ServerTest, HttpSingle200NoContent) {
1062   CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
1063   runner->AddRequestRunner(
1064       StaticHttpRequestRunner::Create200("200.html", false));
1065   runner->ExecuteTest();
1066   ReleaseAndWaitForDestructor(runner);
1067 }
1068 
1069 // Verify handling of a single HTTP 404 request.
TEST(ServerTest,HttpSingle404)1070 TEST(ServerTest, HttpSingle404) {
1071   CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
1072   runner->AddRequestRunner(StaticHttpRequestRunner::Create404("404.html"));
1073   runner->ExecuteTest();
1074   ReleaseAndWaitForDestructor(runner);
1075 }
1076 
1077 // Verify handling of a single HTTP 500 request.
TEST(ServerTest,HttpSingle500)1078 TEST(ServerTest, HttpSingle500) {
1079   CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
1080   runner->AddRequestRunner(StaticHttpRequestRunner::Create500("500.html"));
1081   runner->ExecuteTest();
1082   ReleaseAndWaitForDestructor(runner);
1083 }
1084 
1085 // Verify handling of a single HTTP custom request.
TEST(ServerTest,HttpSingleCustom)1086 TEST(ServerTest, HttpSingleCustom) {
1087   CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
1088   runner->AddRequestRunner(StaticHttpRequestRunner::CreateCustom("202.html"));
1089   runner->ExecuteTest();
1090   ReleaseAndWaitForDestructor(runner);
1091 }
1092 
1093 // Verify handling of a single HTTP custom request with no content.
TEST(ServerTest,HttpSingleCustomNoContent)1094 TEST(ServerTest, HttpSingleCustomNoContent) {
1095   CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
1096   runner->AddRequestRunner(
1097       StaticHttpRequestRunner::CreateCustom("202.html", false));
1098   runner->ExecuteTest();
1099   ReleaseAndWaitForDestructor(runner);
1100 }
1101 
1102 // Verify handling of a single HTTP custom request with no Content-Length
1103 // header.
TEST(ServerTest,HttpSingleCustomNoContentLength)1104 TEST(ServerTest, HttpSingleCustomNoContentLength) {
1105   CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
1106   runner->AddRequestRunner(
1107       StaticHttpRequestRunner::CreateCustom("202.html", true, false));
1108   runner->ExecuteTest();
1109   ReleaseAndWaitForDestructor(runner);
1110 }
1111 
1112 // Verify handling of a single HTTP custom request with no content and no
1113 // Content-Length header.
TEST(ServerTest,HttpSingleCustomNoContentAndNoLength)1114 TEST(ServerTest, HttpSingleCustomNoContentAndNoLength) {
1115   CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
1116   runner->AddRequestRunner(
1117       StaticHttpRequestRunner::CreateCustom("202.html", false, false));
1118   runner->ExecuteTest();
1119   ReleaseAndWaitForDestructor(runner);
1120 }
1121 
1122 // Verify handling of multiple HTTP requests in parallel.
TEST(ServerTest,HttpMultipleParallel200)1123 TEST(ServerTest, HttpMultipleParallel200) {
1124   CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(true);
1125   runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200a.html"));
1126   runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200b.html"));
1127   runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200c.html"));
1128   runner->ExecuteTest();
1129   ReleaseAndWaitForDestructor(runner);
1130 }
1131 
1132 // Verify handling of multiple HTTP requests in serial.
TEST(ServerTest,HttpMultipleSerial200)1133 TEST(ServerTest, HttpMultipleSerial200) {
1134   CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
1135   runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200a.html"));
1136   runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200b.html"));
1137   runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200c.html"));
1138   runner->ExecuteTest();
1139   ReleaseAndWaitForDestructor(runner);
1140 }
1141 
1142 // Verify handling of multiple HTTP requests in parallel.
TEST(ServerTest,HttpMultipleParallelMixed)1143 TEST(ServerTest, HttpMultipleParallelMixed) {
1144   CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(true);
1145   runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200.html"));
1146   runner->AddRequestRunner(StaticHttpRequestRunner::Create404("404.html"));
1147   runner->AddRequestRunner(StaticHttpRequestRunner::Create500("500.html"));
1148   runner->AddRequestRunner(StaticHttpRequestRunner::CreateCustom("202.html"));
1149   runner->ExecuteTest();
1150   ReleaseAndWaitForDestructor(runner);
1151 }
1152 
1153 // Verify handling of multiple HTTP requests in serial.
TEST(ServerTest,HttpMultipleSerialMixed)1154 TEST(ServerTest, HttpMultipleSerialMixed) {
1155   CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
1156   runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200.html"));
1157   runner->AddRequestRunner(StaticHttpRequestRunner::Create404("404.html"));
1158   runner->AddRequestRunner(StaticHttpRequestRunner::Create500("500.html"));
1159   runner->AddRequestRunner(StaticHttpRequestRunner::CreateCustom("202.html"));
1160   runner->ExecuteTest();
1161   ReleaseAndWaitForDestructor(runner);
1162 }
1163 
1164 namespace {
1165 
1166 // WEBSOCKET TESTS
1167 
1168 const char kWebSocketUrl[] = "http://tests-display/websocket.html";
1169 const char kDoneMsgPrefix[] = "done:";
1170 
1171 class WebSocketTestHandler : public RoutingTestHandler {
1172  public:
WebSocketTestHandler()1173   WebSocketTestHandler() {}
1174 
RunTest()1175   void RunTest() override {
1176     handler_ = new TestServerHandler(
1177         base::BindOnce(&WebSocketTestHandler::OnServerStarted, this),
1178         base::BindOnce(&WebSocketTestHandler::OnServerDestroyed, this));
1179     OnHandlerCreated(handler_);
1180 
1181     handler_->CreateServer();
1182 
1183     // Time out the test after a reasonable period of time.
1184     SetTestTimeout();
1185   }
1186 
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)1187   bool OnQuery(CefRefPtr<CefBrowser> browser,
1188                CefRefPtr<CefFrame> frame,
1189                int64 query_id,
1190                const CefString& request,
1191                bool persistent,
1192                CefRefPtr<Callback> callback) override {
1193     const std::string& request_str = request.ToString();
1194     if (request_str.find(kDoneMsgPrefix) == 0) {
1195       EXPECT_FALSE(got_done_message_);
1196       got_done_message_.yes();
1197       OnDoneMessage(request_str.substr(strlen(kDoneMsgPrefix)));
1198       DestroyTestIfDone();
1199       return true;
1200     }
1201     return false;
1202   }
1203 
DestroyTest()1204   void DestroyTest() override {
1205     EXPECT_TRUE(got_server_started_);
1206     EXPECT_TRUE(got_done_message_);
1207     EXPECT_TRUE(got_server_destroyed_);
1208 
1209     TestHandler::DestroyTest();
1210   }
1211 
1212  protected:
1213   // Returns the HTML/JS for the client.
1214   virtual std::string GetClientHtml() = 0;
1215 
1216   // Called after the server handler is created to set test expectations.
1217   virtual void OnHandlerCreated(CefRefPtr<TestServerHandler> handler) = 0;
1218 
1219   // Returns the JS to execute when the test is done.
GetDoneJS(const std::string & result)1220   std::string GetDoneJS(const std::string& result) {
1221     return "window.testQuery({request:'" + std::string(kDoneMsgPrefix) +
1222            "' + " + result + "});";
1223   }
1224 
1225   // Called with the result from the done message.
1226   virtual void OnDoneMessage(const std::string& result) = 0;
1227 
ShutdownServer()1228   void ShutdownServer() {
1229     EXPECT_TRUE(handler_);
1230     handler_->ShutdownServer();
1231     handler_ = nullptr;
1232   }
1233 
1234  private:
OnServerStarted()1235   void OnServerStarted() {
1236     EXPECT_UI_THREAD();
1237     EXPECT_FALSE(got_server_started_);
1238     got_server_started_.yes();
1239 
1240     // Add the WebSocket client code.
1241     AddResource(kWebSocketUrl, GetClientHtml(), "text/html");
1242 
1243     // Create the browser.
1244     CreateBrowser(kWebSocketUrl);
1245   }
1246 
OnServerDestroyed()1247   void OnServerDestroyed() {
1248     EXPECT_UI_THREAD();
1249     EXPECT_FALSE(got_server_destroyed_);
1250     got_server_destroyed_.yes();
1251     DestroyTestIfDone();
1252   }
1253 
DestroyTestIfDone()1254   void DestroyTestIfDone() {
1255     if (got_server_destroyed_ && got_done_message_) {
1256       // Allow the call stack to unwind.
1257       CefPostTask(TID_UI,
1258                   base::BindOnce(&WebSocketTestHandler::DestroyTest, this));
1259     }
1260   }
1261 
1262   CefRefPtr<TestServerHandler> handler_;
1263 
1264   TrackCallback got_server_started_;
1265   TrackCallback got_done_message_;
1266   TrackCallback got_server_destroyed_;
1267 
1268   DISALLOW_COPY_AND_ASSIGN(WebSocketTestHandler);
1269 };
1270 
1271 // WebSocket request handler that echoes each message sent.
1272 class EchoWebSocketRequestHandler : public TestServerHandler::WsRequestHandler {
1273  public:
EchoWebSocketRequestHandler(int expected_message_ct)1274   explicit EchoWebSocketRequestHandler(int expected_message_ct)
1275       : expected_message_ct_(expected_message_ct), actual_message_ct_(0) {}
1276 
GetWebSocketUrl()1277   std::string GetWebSocketUrl() { return GetTestServerOrigin(true) + "/echo"; }
1278 
HandleRequest(CefRefPtr<CefServer> server,int connection_id,const CefString & client_address,CefRefPtr<CefRequest> request,CefRefPtr<CefCallback> callback)1279   bool HandleRequest(CefRefPtr<CefServer> server,
1280                      int connection_id,
1281                      const CefString& client_address,
1282                      CefRefPtr<CefRequest> request,
1283                      CefRefPtr<CefCallback> callback) override {
1284     EXPECT_STREQ(GetWebSocketUrl().c_str(),
1285                  request->GetURL().ToString().c_str());
1286 
1287     callback->Continue();
1288     return true;
1289   }
1290 
HandleConnected(CefRefPtr<CefServer> server,int connection_id)1291   bool HandleConnected(CefRefPtr<CefServer> server,
1292                        int connection_id) override {
1293     return true;
1294   }
1295 
HandleMessage(CefRefPtr<CefServer> server,int connection_id,const void * data,size_t data_size)1296   bool HandleMessage(CefRefPtr<CefServer> server,
1297                      int connection_id,
1298                      const void* data,
1299                      size_t data_size) override {
1300     actual_message_ct_++;
1301 
1302     // Echo the message back to the sender.
1303     server->SendWebSocketMessage(connection_id, data, data_size);
1304 
1305     return true;
1306   }
1307 
VerifyResults()1308   bool VerifyResults() override {
1309     EXPECT_EQ(expected_message_ct_, actual_message_ct_);
1310     return expected_message_ct_ == actual_message_ct_;
1311   }
1312 
ToString()1313   std::string ToString() override { return "EchoRequestHandler"; }
1314 
1315  private:
1316   int expected_message_ct_;
1317   int actual_message_ct_;
1318 
1319   DISALLOW_COPY_AND_ASSIGN(EchoWebSocketRequestHandler);
1320 };
1321 
1322 class EchoWebSocketTestHandler : public WebSocketTestHandler {
1323  public:
1324   // Create |connection_ct| connections and send |message_ct| messages to each
1325   // connection. If |in_parallel| is true the connections will be created in
1326   // parallel.
EchoWebSocketTestHandler(int connection_ct,int message_ct,bool in_parallel)1327   EchoWebSocketTestHandler(int connection_ct, int message_ct, bool in_parallel)
1328       : connection_ct_(connection_ct),
1329         message_ct_(message_ct),
1330         in_parallel_(in_parallel) {}
1331 
GetClientHtml()1332   std::string GetClientHtml() override {
1333     std::stringstream ss;
1334     ss << connection_ct_;
1335     std::string cct_str = ss.str();
1336     ss.str("");
1337     ss << message_ct_;
1338     std::string mct_str = ss.str();
1339 
1340     // clang-format off
1341     return
1342         "<html><body><script>\n"
1343 
1344         // Input variables.
1345         "var url = '" + ws_url_ +"';\n"
1346         "var expected_connection_ct = " + cct_str + ";\n"
1347         "var expected_message_ct = " + mct_str + ";\n"
1348         "var in_parallel = " + (in_parallel_ ? "true" : "false") + ";\n"
1349         "var complete_callback = function() { " +
1350             GetDoneJS("complete_message_ct") + " }\n"
1351 
1352         // Result variables.
1353         "var complete_connection_ct = 0;\n"
1354         "var complete_message_ct = 0;\n"
1355 
1356         // Send the next message on the connection asynchronously, or close the
1357         // connection if all messages have been sent.
1358         "function sendNextMessage(ws, connection_id, message_id) {\n"
1359         "  if (message_id < expected_message_ct) {\n"
1360         "    setTimeout(function() {\n"
1361         "      ws.send('message:' + connection_id + ':' + message_id);\n"
1362         "    }, 1);\n"
1363         "  } else {\n"
1364         "    ws.close();\n"
1365         "  }\n"
1366         "}\n"
1367 
1368         // Handle a received message.
1369         "function onMessage(ws, connection_id, data) {\n"
1370         "  var parts = data.split(':');\n"
1371         "  if (parts.length == 3 && parts[0] == 'message') {\n"
1372         "    var cid = parseInt(parts[1]);\n"
1373         "    var mid = parseInt(parts[2]);\n"
1374         "    if (cid == connection_id) {\n"
1375         "      complete_message_ct++;\n"
1376         "      sendNextMessage(ws, connection_id, mid + 1);\n"
1377         "    } else {\n"
1378         "      console.log('Connection id mismatch; expected ' +\n"
1379         "                  connection_id + ', actual ' + cid);\n"
1380         "    }\n"
1381         "  } else {\n"
1382         "    console.log('Unexpected message format: ' + data);\n"
1383         "  }\n"
1384         "}\n"
1385 
1386         // Handle socket closed. If all messages have been sent on all
1387         // connections then complete the test.
1388         "function onClose(ws) {\n"
1389         "  if (++complete_connection_ct == expected_connection_ct) {\n"
1390         "    complete_callback();\n"
1391         "  } else if (!in_parallel) {\n"
1392         "    startConnection(complete_connection_ct);\n"
1393         "  }\n"
1394         "}\n"
1395 
1396         // Start a new WebSocket connection.
1397         "function startConnection(connection_id) {\n"
1398         "  var ws = new WebSocket(url);\n"
1399         "  ws.onopen = function() {\n"
1400         "    sendNextMessage(ws, connection_id, 0);\n"
1401         "  };\n"
1402         "  ws.onmessage = function(event) {\n"
1403         "    onMessage(ws, connection_id, event.data);\n"
1404         "  };\n"
1405         "  ws.onclose = function() { onClose(ws); };\n"
1406         "}\n"
1407 
1408         // JS entry point.
1409         "if (in_parallel) {\n"
1410         "  for (var i = 0; i < expected_connection_ct; ++i) {\n"
1411         "    startConnection(i);\n"
1412         "  }\n"
1413         "} else {\n"
1414         "  startConnection(0);\n"
1415         "}\n"
1416 
1417         "</script>WebSocket Test</body></html>";
1418     // clang-format on
1419   }
1420 
OnHandlerCreated(CefRefPtr<TestServerHandler> handler)1421   void OnHandlerCreated(CefRefPtr<TestServerHandler> handler) override {
1422     handler->SetExpectedConnectionCount(connection_ct_);
1423     handler->SetExpectedWsRequestCount(connection_ct_);
1424     handler->SetExpectedWsConnectedCount(connection_ct_);
1425     handler->SetExpectedWsMessageCount(connection_ct_ * message_ct_);
1426 
1427     auto echo_handler = std::make_unique<EchoWebSocketRequestHandler>(
1428         connection_ct_ * message_ct_);
1429     ws_url_ = echo_handler->GetWebSocketUrl();
1430     handler->AddWsRequestHandler(std::move(echo_handler));
1431   }
1432 
OnDoneMessage(const std::string & result)1433   void OnDoneMessage(const std::string& result) override {
1434     const int complete_message_ct = atoi(result.c_str());
1435     EXPECT_EQ(connection_ct_ * message_ct_, complete_message_ct);
1436     ShutdownServer();
1437   }
1438 
1439  private:
1440   int connection_ct_;
1441   int message_ct_;
1442   bool in_parallel_;
1443   std::string ws_url_;
1444 
1445   IMPLEMENT_REFCOUNTING(EchoWebSocketTestHandler);
1446   DISALLOW_COPY_AND_ASSIGN(EchoWebSocketTestHandler);
1447 };
1448 
1449 }  // namespace
1450 
1451 // Test handling of a single connection with a single message.
TEST(ServerTest,WebSocketSingleConnectionSingleMessage)1452 TEST(ServerTest, WebSocketSingleConnectionSingleMessage) {
1453   CefRefPtr<EchoWebSocketTestHandler> handler =
1454       new EchoWebSocketTestHandler(1, 1, true);
1455   handler->ExecuteTest();
1456   ReleaseAndWaitForDestructor(handler);
1457 }
1458 
1459 // Test handling of a single connection with multiple messages.
TEST(ServerTest,WebSocketSingleConnectionMultipleMessages)1460 TEST(ServerTest, WebSocketSingleConnectionMultipleMessages) {
1461   CefRefPtr<EchoWebSocketTestHandler> handler =
1462       new EchoWebSocketTestHandler(1, 5, true);
1463   handler->ExecuteTest();
1464   ReleaseAndWaitForDestructor(handler);
1465 }
1466 
1467 // Test handling of multiple connections and multiple messages in parallel.
TEST(ServerTest,WebSocketMultipleConnectionsMultipleMessagesInParallel)1468 TEST(ServerTest, WebSocketMultipleConnectionsMultipleMessagesInParallel) {
1469   CefRefPtr<EchoWebSocketTestHandler> handler =
1470       new EchoWebSocketTestHandler(4, 6, true);
1471   handler->ExecuteTest();
1472   ReleaseAndWaitForDestructor(handler);
1473 }
1474 
1475 // Test handling of multiple connections and multiple messages in serial.
TEST(ServerTest,WebSocketMultipleConnectionsMultipleMessagesInSerial)1476 TEST(ServerTest, WebSocketMultipleConnectionsMultipleMessagesInSerial) {
1477   CefRefPtr<EchoWebSocketTestHandler> handler =
1478       new EchoWebSocketTestHandler(4, 6, false);
1479   handler->ExecuteTest();
1480   ReleaseAndWaitForDestructor(handler);
1481 }
1482