Save errno for logging before potentially overwriting it.
[chromium-blink-merge.git] / content / browser / plugin_loader_posix_unittest.cc
blob871891b1588c85697a5d31c543ba30f963ba518f
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 #include "content/browser/plugin_loader_posix.h"
7 #include "base/at_exit.h"
8 #include "base/bind.h"
9 #include "base/files/file_path.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/message_loop.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "content/browser/browser_thread_impl.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "webkit/plugins/webplugininfo.h"
18 namespace content {
20 class MockPluginLoaderPosix : public PluginLoaderPosix {
21 public:
22 MOCK_METHOD0(LoadPluginsInternal, void(void));
24 size_t number_of_pending_callbacks() {
25 return callbacks_.size();
28 std::vector<base::FilePath>* canonical_list() {
29 return &canonical_list_;
32 size_t next_load_index() {
33 return next_load_index_;
36 const std::vector<webkit::WebPluginInfo>& loaded_plugins() {
37 return loaded_plugins_;
40 std::vector<webkit::WebPluginInfo>* internal_plugins() {
41 return &internal_plugins_;
44 void RealLoadPluginsInternal() {
45 PluginLoaderPosix::LoadPluginsInternal();
48 void TestOnPluginLoaded(uint32 index, const webkit::WebPluginInfo& plugin) {
49 OnPluginLoaded(index, plugin);
52 void TestOnPluginLoadFailed(uint32 index, const base::FilePath& path) {
53 OnPluginLoadFailed(index, path);
56 protected:
57 virtual ~MockPluginLoaderPosix() {}
60 void VerifyCallback(int* run_count, const std::vector<webkit::WebPluginInfo>&) {
61 ++(*run_count);
64 class PluginLoaderPosixTest : public testing::Test {
65 public:
66 PluginLoaderPosixTest()
67 : plugin1_(ASCIIToUTF16("plugin1"), base::FilePath("/tmp/one.plugin"),
68 ASCIIToUTF16("1.0"), string16()),
69 plugin2_(ASCIIToUTF16("plugin2"), base::FilePath("/tmp/two.plugin"),
70 ASCIIToUTF16("2.0"), string16()),
71 plugin3_(ASCIIToUTF16("plugin3"), base::FilePath("/tmp/three.plugin"),
72 ASCIIToUTF16("3.0"), string16()),
73 file_thread_(BrowserThread::FILE, &message_loop_),
74 io_thread_(BrowserThread::IO, &message_loop_),
75 plugin_loader_(new MockPluginLoaderPosix) {
78 virtual void SetUp() OVERRIDE {
79 PluginServiceImpl::GetInstance()->Init();
82 base::MessageLoop* message_loop() { return &message_loop_; }
83 MockPluginLoaderPosix* plugin_loader() { return plugin_loader_.get(); }
85 void AddThreePlugins() {
86 plugin_loader_->canonical_list()->clear();
87 plugin_loader_->canonical_list()->push_back(plugin1_.path);
88 plugin_loader_->canonical_list()->push_back(plugin2_.path);
89 plugin_loader_->canonical_list()->push_back(plugin3_.path);
92 // Data used for testing.
93 webkit::WebPluginInfo plugin1_;
94 webkit::WebPluginInfo plugin2_;
95 webkit::WebPluginInfo plugin3_;
97 private:
98 base::ShadowingAtExitManager at_exit_manager_; // Destroys PluginService.
100 base::MessageLoopForIO message_loop_;
101 BrowserThreadImpl file_thread_;
102 BrowserThreadImpl io_thread_;
104 scoped_refptr<MockPluginLoaderPosix> plugin_loader_;
107 TEST_F(PluginLoaderPosixTest, QueueRequests) {
108 int did_callback = 0;
109 PluginService::GetPluginsCallback callback =
110 base::Bind(&VerifyCallback, base::Unretained(&did_callback));
112 EXPECT_EQ(0u, plugin_loader()->number_of_pending_callbacks());
113 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback);
114 EXPECT_EQ(1u, plugin_loader()->number_of_pending_callbacks());
116 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback);
117 EXPECT_EQ(2u, plugin_loader()->number_of_pending_callbacks());
119 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(2);
120 message_loop()->RunUntilIdle();
122 EXPECT_EQ(0, did_callback);
124 plugin_loader()->canonical_list()->clear();
125 plugin_loader()->canonical_list()->push_back(plugin1_.path);
126 plugin_loader()->TestOnPluginLoaded(0, plugin1_);
127 message_loop()->RunUntilIdle();
129 EXPECT_EQ(1, did_callback);
130 EXPECT_EQ(1u, plugin_loader()->number_of_pending_callbacks());
132 plugin_loader()->canonical_list()->clear();
133 plugin_loader()->canonical_list()->push_back(plugin1_.path);
134 plugin_loader()->TestOnPluginLoaded(0, plugin1_);
135 message_loop()->RunUntilIdle();
137 EXPECT_EQ(2, did_callback);
138 EXPECT_EQ(0u, plugin_loader()->number_of_pending_callbacks());
141 TEST_F(PluginLoaderPosixTest, ThreeSuccessfulLoads) {
142 int did_callback = 0;
143 PluginService::GetPluginsCallback callback =
144 base::Bind(&VerifyCallback, base::Unretained(&did_callback));
146 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback);
148 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
149 message_loop()->RunUntilIdle();
151 AddThreePlugins();
153 EXPECT_EQ(0u, plugin_loader()->next_load_index());
155 const std::vector<webkit::WebPluginInfo>& plugins(
156 plugin_loader()->loaded_plugins());
158 plugin_loader()->TestOnPluginLoaded(0, plugin1_);
159 EXPECT_EQ(1u, plugin_loader()->next_load_index());
160 EXPECT_EQ(1u, plugins.size());
161 EXPECT_EQ(plugin1_.name, plugins[0].name);
163 message_loop()->RunUntilIdle();
164 EXPECT_EQ(0, did_callback);
166 plugin_loader()->TestOnPluginLoaded(1, plugin2_);
167 EXPECT_EQ(2u, plugin_loader()->next_load_index());
168 EXPECT_EQ(2u, plugins.size());
169 EXPECT_EQ(plugin2_.name, plugins[1].name);
171 message_loop()->RunUntilIdle();
172 EXPECT_EQ(0, did_callback);
174 plugin_loader()->TestOnPluginLoaded(2, plugin3_);
175 EXPECT_EQ(3u, plugins.size());
176 EXPECT_EQ(plugin3_.name, plugins[2].name);
178 message_loop()->RunUntilIdle();
179 EXPECT_EQ(1, did_callback);
182 TEST_F(PluginLoaderPosixTest, ThreeSuccessfulLoadsThenCrash) {
183 int did_callback = 0;
184 PluginService::GetPluginsCallback callback =
185 base::Bind(&VerifyCallback, base::Unretained(&did_callback));
187 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback);
189 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(2);
190 message_loop()->RunUntilIdle();
192 AddThreePlugins();
194 EXPECT_EQ(0u, plugin_loader()->next_load_index());
196 const std::vector<webkit::WebPluginInfo>& plugins(
197 plugin_loader()->loaded_plugins());
199 plugin_loader()->TestOnPluginLoaded(0, plugin1_);
200 EXPECT_EQ(1u, plugin_loader()->next_load_index());
201 EXPECT_EQ(1u, plugins.size());
202 EXPECT_EQ(plugin1_.name, plugins[0].name);
204 message_loop()->RunUntilIdle();
205 EXPECT_EQ(0, did_callback);
207 plugin_loader()->TestOnPluginLoaded(1, plugin2_);
208 EXPECT_EQ(2u, plugin_loader()->next_load_index());
209 EXPECT_EQ(2u, plugins.size());
210 EXPECT_EQ(plugin2_.name, plugins[1].name);
212 message_loop()->RunUntilIdle();
213 EXPECT_EQ(0, did_callback);
215 plugin_loader()->TestOnPluginLoaded(2, plugin3_);
216 EXPECT_EQ(3u, plugins.size());
217 EXPECT_EQ(plugin3_.name, plugins[2].name);
219 message_loop()->RunUntilIdle();
220 EXPECT_EQ(1, did_callback);
222 plugin_loader()->OnProcessCrashed(42);
225 TEST_F(PluginLoaderPosixTest, TwoFailures) {
226 int did_callback = 0;
227 PluginService::GetPluginsCallback callback =
228 base::Bind(&VerifyCallback, base::Unretained(&did_callback));
230 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback);
232 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
233 message_loop()->RunUntilIdle();
235 AddThreePlugins();
237 EXPECT_EQ(0u, plugin_loader()->next_load_index());
239 const std::vector<webkit::WebPluginInfo>& plugins(
240 plugin_loader()->loaded_plugins());
242 plugin_loader()->TestOnPluginLoadFailed(0, plugin1_.path);
243 EXPECT_EQ(1u, plugin_loader()->next_load_index());
244 EXPECT_EQ(0u, plugins.size());
246 message_loop()->RunUntilIdle();
247 EXPECT_EQ(0, did_callback);
249 plugin_loader()->TestOnPluginLoaded(1, plugin2_);
250 EXPECT_EQ(2u, plugin_loader()->next_load_index());
251 EXPECT_EQ(1u, plugins.size());
252 EXPECT_EQ(plugin2_.name, plugins[0].name);
254 message_loop()->RunUntilIdle();
255 EXPECT_EQ(0, did_callback);
257 plugin_loader()->TestOnPluginLoadFailed(2, plugin3_.path);
258 EXPECT_EQ(1u, plugins.size());
260 message_loop()->RunUntilIdle();
261 EXPECT_EQ(1, did_callback);
264 TEST_F(PluginLoaderPosixTest, CrashedProcess) {
265 int did_callback = 0;
266 PluginService::GetPluginsCallback callback =
267 base::Bind(&VerifyCallback, base::Unretained(&did_callback));
269 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback);
271 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
272 message_loop()->RunUntilIdle();
274 AddThreePlugins();
276 EXPECT_EQ(0u, plugin_loader()->next_load_index());
278 const std::vector<webkit::WebPluginInfo>& plugins(
279 plugin_loader()->loaded_plugins());
281 plugin_loader()->TestOnPluginLoaded(0, plugin1_);
282 EXPECT_EQ(1u, plugin_loader()->next_load_index());
283 EXPECT_EQ(1u, plugins.size());
284 EXPECT_EQ(plugin1_.name, plugins[0].name);
286 message_loop()->RunUntilIdle();
287 EXPECT_EQ(0, did_callback);
289 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
290 plugin_loader()->OnProcessCrashed(42);
291 EXPECT_EQ(1u, plugin_loader()->canonical_list()->size());
292 EXPECT_EQ(0u, plugin_loader()->next_load_index());
293 EXPECT_EQ(plugin3_.path.value(),
294 plugin_loader()->canonical_list()->at(0).value());
297 TEST_F(PluginLoaderPosixTest, InternalPlugin) {
298 int did_callback = 0;
299 PluginService::GetPluginsCallback callback =
300 base::Bind(&VerifyCallback, base::Unretained(&did_callback));
302 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback);
304 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
305 message_loop()->RunUntilIdle();
307 plugin2_.path = base::FilePath("/internal/plugin.plugin");
309 AddThreePlugins();
311 plugin_loader()->internal_plugins()->clear();
312 plugin_loader()->internal_plugins()->push_back(plugin2_);
314 EXPECT_EQ(0u, plugin_loader()->next_load_index());
316 const std::vector<webkit::WebPluginInfo>& plugins(
317 plugin_loader()->loaded_plugins());
319 plugin_loader()->TestOnPluginLoaded(0, plugin1_);
320 EXPECT_EQ(1u, plugin_loader()->next_load_index());
321 EXPECT_EQ(1u, plugins.size());
322 EXPECT_EQ(plugin1_.name, plugins[0].name);
324 message_loop()->RunUntilIdle();
325 EXPECT_EQ(0, did_callback);
327 // Internal plugins can fail to load if they're built-in with manual
328 // entrypoint functions.
329 plugin_loader()->TestOnPluginLoadFailed(1, plugin2_.path);
330 EXPECT_EQ(2u, plugin_loader()->next_load_index());
331 EXPECT_EQ(2u, plugins.size());
332 EXPECT_EQ(plugin2_.name, plugins[1].name);
333 EXPECT_EQ(0u, plugin_loader()->internal_plugins()->size());
335 message_loop()->RunUntilIdle();
336 EXPECT_EQ(0, did_callback);
338 plugin_loader()->TestOnPluginLoaded(2, plugin3_);
339 EXPECT_EQ(3u, plugins.size());
340 EXPECT_EQ(plugin3_.name, plugins[2].name);
342 message_loop()->RunUntilIdle();
343 EXPECT_EQ(1, did_callback);
346 TEST_F(PluginLoaderPosixTest, AllCrashed) {
347 int did_callback = 0;
348 PluginService::GetPluginsCallback callback =
349 base::Bind(&VerifyCallback, base::Unretained(&did_callback));
351 plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback);
353 // Spin the loop so that the canonical list of plugins can be set.
354 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
355 message_loop()->RunUntilIdle();
356 AddThreePlugins();
358 EXPECT_EQ(0u, plugin_loader()->next_load_index());
360 // Mock the first two calls like normal.
361 testing::Expectation first =
362 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(2);
363 // On the last call, go through the default impl.
364 EXPECT_CALL(*plugin_loader(), LoadPluginsInternal())
365 .After(first)
366 .WillOnce(
367 testing::Invoke(plugin_loader(),
368 &MockPluginLoaderPosix::RealLoadPluginsInternal));
369 plugin_loader()->OnProcessCrashed(42);
370 plugin_loader()->OnProcessCrashed(42);
371 plugin_loader()->OnProcessCrashed(42);
373 message_loop()->RunUntilIdle();
374 EXPECT_EQ(1, did_callback);
376 EXPECT_EQ(0u, plugin_loader()->loaded_plugins().size());
379 } // namespace content