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