Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1136)

Side by Side Diff: chrome/test/base/mojo_test_connector.cc

Issue 1806353003: Adds option to run browser tests in mash (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: format Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/test/base/mojo_test_connector.h ('k') | content/public/test/test_launcher.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/test/base/mojo_test_connector.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/command_line.h"
10 #include "base/run_loop.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/thread.h"
14 #include "content/public/common/content_switches.h"
15 #include "content/public/test/test_launcher.h"
16 #include "mojo/edk/embedder/embedder.h"
17 #include "mojo/edk/embedder/platform_channel_pair.h"
18 #include "mojo/edk/embedder/process_delegate.h"
19 #include "mojo/public/cpp/bindings/interface_request.h"
20 #include "mojo/services/catalog/store.h"
21 #include "mojo/shell/background/tests/test_catalog_store.h"
22 #include "mojo/shell/public/cpp/connector.h"
23 #include "mojo/shell/public/cpp/shell_client.h"
24 #include "mojo/shell/public/cpp/shell_connection.h"
25 #include "mojo/shell/runner/common/client_util.h"
26 #include "mojo/shell/runner/common/switches.h"
27 #include "mojo/shell/shell.h"
28 #include "mojo/shell/switches.h"
29
30 using mojo::shell::mojom::ShellClient;
31 using mojo::shell::mojom::ShellClientPtr;
32
33 namespace {
34
35 const char kTestRunnerName[] = "mojo:test-runner";
36 const char kTestName[] = "exe:chrome";
37
38 // Returns the Dictionary value of |parent| under the specified key, creating
39 // and adding as necessary.
40 base::DictionaryValue* EnsureDictionary(base::DictionaryValue* parent,
41 const char* key) {
42 base::DictionaryValue* dictionary = nullptr;
43 if (parent->GetDictionary(key, &dictionary))
44 return dictionary;
45
46 scoped_ptr<base::DictionaryValue> owned_dictionary(new base::DictionaryValue);
47 dictionary = owned_dictionary.get();
48 parent->Set(key, std::move(owned_dictionary));
49 return dictionary;
50 }
51
52 // This builds a permissive catalog with the addition of the 'instance_name'
53 // permission.
54 scoped_ptr<mojo::shell::TestCatalogStore> BuildTestCatalogStore() {
55 scoped_ptr<base::ListValue> apps(new base::ListValue);
56 scoped_ptr<base::DictionaryValue> test_app_config =
57 mojo::shell::BuildPermissiveSerializedAppInfo(kTestRunnerName, "test");
58 base::DictionaryValue* capabilities =
59 EnsureDictionary(test_app_config.get(), catalog::Store::kCapabilitiesKey);
60 base::DictionaryValue* required_capabilities =
61 EnsureDictionary(capabilities, catalog::Store::kCapabilities_RequiredKey);
62 scoped_ptr<base::ListValue> required_shell_classes(new base::ListValue);
63 required_shell_classes->AppendString("instance_name");
64 required_shell_classes->AppendString("client_process");
65 scoped_ptr<base::DictionaryValue> shell_caps(new base::DictionaryValue);
66 shell_caps->Set(catalog::Store::kCapabilities_ClassesKey,
67 std::move(required_shell_classes));
68 required_capabilities->Set("mojo:shell", std::move(shell_caps));
69 apps->Append(std::move(test_app_config));
70 return make_scoped_ptr(new mojo::shell::TestCatalogStore(std::move(apps)));
71 }
72
73 // BackgroundTestState maintains all the state necessary to bind the test to
74 // mojo. This class is only used on the thread created by BackgroundShell.
75 class BackgroundTestState {
76 public:
77 BackgroundTestState() {}
78 ~BackgroundTestState() {}
79
80 // Prepares the command line and other setup for connecting the test to mojo.
81 // Must be paired with a clal to ChildProcessLaunched().
82 void Connect(base::CommandLine* command_line,
83 mojo::shell::Shell* shell,
84 const std::string& instance,
85 base::TestLauncher::LaunchOptions* test_launch_options) {
86 command_line->AppendSwitch(MojoTestConnector::kTestSwitch);
87 command_line->AppendSwitch(switches::kWaitForMojoShell);
88 command_line->AppendSwitch(switches::kChildProcess);
89 mojo_ipc_channel_.reset(new mojo::edk::PlatformChannelPair);
90 mojo_ipc_channel_->PrepareToPassClientHandleToChildProcess(
91 command_line, &handle_passing_info_);
92 #if defined(OS_WIN)
93 test_launch_options->inherit_handles = true;
94 test_launch_options->handles_to_inherit = &handle_passing_info_;
95 #if defined(OFFICIAL_BUILD)
96 CHECK(false) << "Launching mojo process with inherit_handles is insecure!";
97 #endif
98 #elif defined(OS_POSIX)
99 test_launch_options->fds_to_remap = &handle_passing_info_;
100 #else
101 #error "Unsupported"
102 #endif
103 mojo::shell::mojom::ShellClientPtr client =
104 mojo::shell::PassShellClientRequestOnCommandLine(command_line);
105
106 scoped_ptr<mojo::shell::ConnectParams> params(
107 new mojo::shell::ConnectParams);
108 params->set_source(mojo::shell::CreateShellIdentity());
109 params->set_target(
110 mojo::Identity(kTestName, mojo::shell::mojom::kRootUserID, instance));
111
112 mojo::shell::mojom::ClientProcessConnectionPtr client_process_connection =
113 mojo::shell::mojom::ClientProcessConnection::New();
114 client_process_connection->shell_client =
115 client.PassInterface().PassHandle();
116 client_process_connection->pid_receiver_request =
117 mojo::GetProxy(&pid_receiver_).PassMessagePipe();
118 params->set_client_process_connection(std::move(client_process_connection));
119 shell->Connect(std::move(params));
120 }
121
122 // Called after the test process has launched. Completes the registration done
123 // in Connect().
124 void ChildProcessLaunched(base::ProcessHandle handle, base::ProcessId pid) {
125 pid_receiver_->SetPID(pid);
126 mojo_ipc_channel_->ChildProcessLaunched();
127 mojo::edk::ChildProcessLaunched(
128 handle, mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle(
129 mojo_ipc_channel_->PassServerHandle().release().handle)));
130 }
131
132 private:
133 // Used to back the NodeChannel between the parent and child node.
134 scoped_ptr<mojo::edk::PlatformChannelPair> mojo_ipc_channel_;
135
136 mojo::edk::HandlePassingInformation handle_passing_info_;
137
138 mojo::shell::mojom::PIDReceiverPtr pid_receiver_;
139
140 DISALLOW_COPY_AND_ASSIGN(BackgroundTestState);
141 };
142
143 // Called used destroy BackgroundTestState on the background thread.
144 void DestroyBackgroundStateOnBackgroundThread(
145 scoped_ptr<BackgroundTestState> state,
146 mojo::shell::Shell* shell) {}
147
148 // State created per test. Manages creation of the corresponding
149 // BackgroundTestState and making sure processing runs on the right threads.
150 class MojoTestState : public content::TestState {
151 public:
152 explicit MojoTestState(mojo::shell::BackgroundShell* background_shell)
153 : background_shell_(background_shell) {}
154
155 ~MojoTestState() override {
156 DCHECK(background_state_);
157 // BackgroundState needs to be destroyed on the background thread. We're
158 // guaranteed |background_shell_| has been created by the time we reach
159 // here as Init() blocks until |background_shell_| has been created.
160 background_shell_->ExecuteOnShellThread(
161 base::Bind(&DestroyBackgroundStateOnBackgroundThread,
162 base::Passed(&background_state_)));
163 }
164
165 void Init(base::CommandLine* command_line,
166 base::TestLauncher::LaunchOptions* test_launch_options) {
167 base::WaitableEvent signal(true, false);
168 background_shell_->ExecuteOnShellThread(base::Bind(
169 &MojoTestState::BindOnBackgroundThread, base::Unretained(this), &signal,
170 command_line, test_launch_options));
171 signal.Wait();
172 }
173
174 private:
175 // content::TestState:
176 void ChildProcessLaunched(base::ProcessHandle handle,
177 base::ProcessId pid) override {
178 // This is called on a random thread. We need to ensure BackgroundTestState
179 // is only called on the background thread, and we wait for
180 // ChildProcessLaunchedOnBackgroundThread() to be run before continuing so
181 // that |handle| is still valid.
182 base::WaitableEvent signal(true, false);
183 background_shell_->ExecuteOnShellThread(
184 base::Bind(&MojoTestState::ChildProcessLaunchedOnBackgroundThread,
185 base::Unretained(this), handle, pid, &signal));
186 signal.Wait();
187 }
188
189 void ChildProcessLaunchedOnBackgroundThread(base::ProcessHandle handle,
190 base::ProcessId pid,
191 base::WaitableEvent* signal,
192 mojo::shell::Shell* shell) {
193 background_state_->ChildProcessLaunched(handle, pid);
194 signal->Signal();
195 }
196
197 void BindOnBackgroundThread(
198 base::WaitableEvent* signal,
199 base::CommandLine* command_line,
200 base::TestLauncher::LaunchOptions* test_launch_options,
201 mojo::shell::Shell* shell) {
202 static int instance_id = 0;
203 const std::string instance_name =
204 "instance-" + base::IntToString(instance_id++);
205 background_state_.reset(new BackgroundTestState);
206 background_state_->Connect(command_line, shell, instance_name,
207 test_launch_options);
208 signal->Signal();
209 }
210
211 mojo::shell::BackgroundShell* background_shell_;
212 scoped_ptr<BackgroundTestState> background_state_;
213
214 DISALLOW_COPY_AND_ASSIGN(MojoTestState);
215 };
216
217 } // namespace
218
219 // static
220 const char MojoTestConnector::kTestSwitch[] = "is_test";
221
222 MojoTestConnector::MojoTestConnector() {}
223
224 mojo::shell::mojom::ShellClientRequest MojoTestConnector::Init() {
225 scoped_ptr<mojo::shell::BackgroundShell::InitParams> init_params(
226 new mojo::shell::BackgroundShell::InitParams);
227 init_params->catalog_store = BuildTestCatalogStore();
228 // When running in single_process mode chrome initializes the edk.
229 init_params->init_edk = !base::CommandLine::ForCurrentProcess()->HasSwitch(
230 content::kSingleProcessTestsFlag);
231 background_shell_.Init(std::move(init_params));
232 return background_shell_.CreateShellClientRequest(kTestRunnerName);
233 }
234
235 MojoTestConnector::~MojoTestConnector() {}
236
237 scoped_ptr<content::TestState> MojoTestConnector::PrepareForTest(
238 base::CommandLine* command_line,
239 base::TestLauncher::LaunchOptions* test_launch_options) {
240 scoped_ptr<MojoTestState> test_state(new MojoTestState(&background_shell_));
241 test_state->Init(command_line, test_launch_options);
242 return std::move(test_state);
243 }
OLDNEW
« no previous file with comments | « chrome/test/base/mojo_test_connector.h ('k') | content/public/test/test_launcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698