1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef NET_TEST_SPAWNED_TEST_SERVER_SPAWNER_COMMUNICATOR_H_
6 #define NET_TEST_SPAWNED_TEST_SERVER_SPAWNER_COMMUNICATOR_H_
10 #include "base/basictypes.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "base/threading/thread.h"
15 #include "net/url_request/url_request.h"
19 class ScopedPortException
;
21 // SpawnerCommunicator communicates with a spawner server that runs on a
24 // The test server used by unit tests is written in Python. However, Android
25 // does not support running Python code, so the test server cannot run on the
26 // same device running unit tests.
28 // The actual test server is executed on the host machine, while the unit tests
29 // themselves continue running on the device. To control the test server on the
30 // host machine, a second HTTP server is started, the spawner server, which
31 // controls the life cycle of remote test servers. Calls to start/kill the
32 // SpawnedTestServer are then redirected to the spawner server via
33 // this spawner communicator.
35 // Currently only three commands are supported by spawner.
37 // (1) Start Python test server, format is:
40 // Data to server: all arguments needed to launch the Python test server, in
42 // Data from server: a JSON dict includes the following two field if success,
43 // "port": the port the Python test server actually listen on that.
44 // "message": must be "started".
46 // (2) Kill Python test server, format is:
49 // Data to server: None.
50 // Data from server: String "killed" returned if success.
52 // (3) Ping Python test server to see whether it is alive, format is:
55 // Data to server: None.
56 // Data from server: String "ready" returned if success.
58 // The internal I/O thread is required by net stack to perform net I/O.
59 // The Start/StopServer methods block the caller thread until result is
60 // fetched from spawner server or timed-out.
61 class SpawnerCommunicator
: public URLRequest::Delegate
{
63 explicit SpawnerCommunicator(uint16 port
);
64 ~SpawnerCommunicator() override
;
66 // Starts an instance of the Python test server on the host/ machine.
67 // If successfully started, returns true, setting |*port| to the port
68 // on the local machine that can be used to communicate with the remote
70 bool StartServer(const std::string
& arguments
,
71 uint16
* port
) WARN_UNUSED_RESULT
;
73 bool StopServer() WARN_UNUSED_RESULT
;
76 // Starts the IO thread. Called on the user thread.
79 // Shuts down the remote test server spawner. Called on the user thread.
82 // Waits for the server response on IO thread. Called on the user thread.
83 void WaitForResponse();
85 // Sends a command to the test server over HTTP, returning the result code
86 // |*result_code| and response data in |*data_received|, those two arguments
87 // must be not NULL, otherwise the method returns immediately without sending
88 // the |command|. If |post_data| is empty, HTTP GET will be used to send
89 // |command|. If |post_data| is non-empty, performs an HTTP POST.
90 // This method is called on the user thread.
91 void SendCommandAndWaitForResult(const std::string
& command
,
92 const std::string
& post_data
,
94 std::string
* data_received
);
96 // Performs the command sending on the IO thread. Called on the IO thread.
97 void SendCommandAndWaitForResultOnIOThread(const std::string
& command
,
98 const std::string
& post_data
,
100 std::string
* data_received
);
102 // URLRequest::Delegate methods. Called on the IO thread.
103 void OnResponseStarted(URLRequest
* request
) override
;
104 void OnReadCompleted(URLRequest
* request
, int num_bytes
) override
;
106 // Reads Result from the response. Called on the IO thread.
107 void ReadResult(URLRequest
* request
);
109 // Called on the IO thread upon completion of the spawner command.
110 void OnSpawnerCommandCompleted(URLRequest
* request
);
112 // Callback on the IO thread for time-out task of request with id |id|.
113 void OnTimeout(int id
);
115 // A thread to communicate with test_spawner server.
116 base::Thread io_thread_
;
118 // WaitableEvent to notify whether the communication is done.
119 base::WaitableEvent event_
;
121 // The local port used to communicate with the TestServer spawner. This is
122 // used to control the startup and shutdown of the Python TestServer running
123 // on the remote machine. On Android, this port will be redirected to the
124 // same port on the host machine.
127 // Helper to add |port_| to the list of the globally explicitly allowed ports.
128 scoped_ptr
<ScopedPortException
> allowed_port_
;
130 // The next ID to use for |cur_request_| (monotonically increasing).
133 // Request context used by |cur_request_|.
134 scoped_ptr
<URLRequestContext
> context_
;
136 // The current (in progress) request, or NULL.
137 scoped_ptr
<URLRequest
> cur_request_
;
139 // Only gets/sets |is_running_| on user's thread to avoid race-condition.
142 // Factory for creating the time-out task. This takes care of revoking
143 // outstanding tasks when |this| is deleted.
144 base::WeakPtrFactory
<SpawnerCommunicator
> weak_factory_
;
146 DISALLOW_COPY_AND_ASSIGN(SpawnerCommunicator
);
151 #endif // NET_TEST_SPAWNED_TEST_SERVER_SPAWNER_COMMUNICATOR_H_