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

Side by Side Diff: chrome/common/service_process_util_unittest.cc

Issue 6660001: Getting service process on Mac to handle having things moved/changed underneath it. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix up bad instance reset Created 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/common/service_process_util.h"
6
5 #include "base/basictypes.h" 7 #include "base/basictypes.h"
6 8
7 #if !defined(OS_MACOSX) 9 #if !defined(OS_MACOSX)
8 // TODO(dmaclach): Figure out tests that will work with launchd on Mac OS.
9
10 #include "base/at_exit.h" 10 #include "base/at_exit.h"
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/process_util.h" 12 #include "base/process_util.h"
13 #include "base/scoped_ptr.h" 13 #include "base/scoped_ptr.h"
14 #include "base/string_util.h" 14 #include "base/string_util.h"
15 #include "base/test/multiprocess_test.h" 15 #include "base/test/multiprocess_test.h"
16 #include "base/test/test_timeouts.h" 16 #include "base/test/test_timeouts.h"
17 #include "base/threading/thread.h" 17 #include "base/threading/thread.h"
18 #include "base/utf_string_conversions.h" 18 #include "base/utf_string_conversions.h"
19 #include "chrome/common/chrome_switches.h" 19 #include "chrome/common/chrome_switches.h"
20 #include "chrome/common/chrome_version_info.h" 20 #include "chrome/common/chrome_version_info.h"
21 #include "chrome/common/service_process_util.h"
22 #include "testing/multiprocess_func_list.h" 21 #include "testing/multiprocess_func_list.h"
23 22
24 #if defined(OS_WIN) 23 #if defined(OS_WIN)
25 #include "base/win/win_util.h" 24 #include "base/win/win_util.h"
26 #endif 25 #endif
27 26
28 #if defined(OS_LINUX) 27 #if defined(OS_LINUX)
29 #include <glib.h> 28 #include <glib.h>
30 #include "chrome/common/auto_start_linux.h" 29 #include "chrome/common/auto_start_linux.h"
31 #endif 30 #endif
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 81
83 void ServiceProcessStateTest::LaunchAndWait(const std::string& name) { 82 void ServiceProcessStateTest::LaunchAndWait(const std::string& name) {
84 base::ProcessHandle handle = SpawnChild(name, false); 83 base::ProcessHandle handle = SpawnChild(name, false);
85 ASSERT_TRUE(handle); 84 ASSERT_TRUE(handle);
86 int exit_code = 0; 85 int exit_code = 0;
87 ASSERT_TRUE(base::WaitForExitCode(handle, &exit_code)); 86 ASSERT_TRUE(base::WaitForExitCode(handle, &exit_code));
88 ASSERT_EQ(exit_code, 0); 87 ASSERT_EQ(exit_code, 0);
89 } 88 }
90 89
91 TEST_F(ServiceProcessStateTest, Singleton) { 90 TEST_F(ServiceProcessStateTest, Singleton) {
92 ServiceProcessState* state = ServiceProcessState::GetInstance(); 91 ServiceProcessState state;
93 ASSERT_TRUE(state->Initialize()); 92 ASSERT_TRUE(state.Initialize());
94 LaunchAndWait("ServiceProcessStateTestSingleton"); 93 LaunchAndWait("ServiceProcessStateTestSingleton");
95 } 94 }
96 95
97 TEST_F(ServiceProcessStateTest, ReadyState) { 96 TEST_F(ServiceProcessStateTest, ReadyState) {
98 ASSERT_FALSE(CheckServiceProcessReady()); 97 ASSERT_FALSE(CheckServiceProcessReady());
99 ServiceProcessState* state = ServiceProcessState::GetInstance(); 98 ServiceProcessState state;
100 ASSERT_TRUE(state->Initialize()); 99 ASSERT_TRUE(state.Initialize());
101 ASSERT_TRUE(state->SignalReady(IOMessageLoopProxy(), NULL)); 100 ASSERT_TRUE(state.SignalReady(IOMessageLoopProxy(), NULL));
102 LaunchAndWait("ServiceProcessStateTestReadyTrue"); 101 LaunchAndWait("ServiceProcessStateTestReadyTrue");
103 state->SignalStopped(); 102 state.SignalStopped();
104 LaunchAndWait("ServiceProcessStateTestReadyFalse"); 103 LaunchAndWait("ServiceProcessStateTestReadyFalse");
105 } 104 }
106 105
107 TEST_F(ServiceProcessStateTest, AutoRun) { 106 TEST_F(ServiceProcessStateTest, AutoRun) {
108 ServiceProcessState* state = ServiceProcessState::GetInstance(); 107 ServiceProcessState state;
109 ASSERT_TRUE(state->AddToAutoRun()); 108 ASSERT_TRUE(state.AddToAutoRun());
110 scoped_ptr<CommandLine> autorun_command_line; 109 scoped_ptr<CommandLine> autorun_command_line;
111 #if defined(OS_WIN) 110 #if defined(OS_WIN)
112 std::string value_name = GetServiceProcessScopedName("_service_run"); 111 std::string value_name = GetServiceProcessScopedName("_service_run");
113 string16 value; 112 string16 value;
114 EXPECT_TRUE(base::win::ReadCommandFromAutoRun(HKEY_CURRENT_USER, 113 EXPECT_TRUE(base::win::ReadCommandFromAutoRun(HKEY_CURRENT_USER,
115 UTF8ToWide(value_name), 114 UTF8ToWide(value_name),
116 &value)); 115 &value));
117 autorun_command_line.reset(new CommandLine(CommandLine::FromString(value))); 116 autorun_command_line.reset(new CommandLine(CommandLine::FromString(value)));
118 #elif defined(OS_LINUX) 117 #elif defined(OS_LINUX)
119 #if defined(GOOGLE_CHROME_BUILD) 118 #if defined(GOOGLE_CHROME_BUILD)
(...skipping 12 matching lines...) Expand all
132 g_strfreev(argv); 131 g_strfreev(argv);
133 } else { 132 } else {
134 ADD_FAILURE(); 133 ADD_FAILURE();
135 g_error_free(error); 134 g_error_free(error);
136 } 135 }
137 #endif // defined(OS_WIN) 136 #endif // defined(OS_WIN)
138 if (autorun_command_line.get()) { 137 if (autorun_command_line.get()) {
139 EXPECT_EQ(autorun_command_line->GetSwitchValueASCII(switches::kProcessType), 138 EXPECT_EQ(autorun_command_line->GetSwitchValueASCII(switches::kProcessType),
140 std::string(switches::kServiceProcess)); 139 std::string(switches::kServiceProcess));
141 } 140 }
142 ASSERT_TRUE(state->RemoveFromAutoRun()); 141 ASSERT_TRUE(state.RemoveFromAutoRun());
143 #if defined(OS_WIN) 142 #if defined(OS_WIN)
144 EXPECT_FALSE(base::win::ReadCommandFromAutoRun(HKEY_CURRENT_USER, 143 EXPECT_FALSE(base::win::ReadCommandFromAutoRun(HKEY_CURRENT_USER,
145 UTF8ToWide(value_name), 144 UTF8ToWide(value_name),
146 &value)); 145 &value));
147 #elif defined(OS_LINUX) 146 #elif defined(OS_LINUX)
148 EXPECT_FALSE(AutoStart::GetAutostartFileValue( 147 EXPECT_FALSE(AutoStart::GetAutostartFileValue(
149 GetServiceProcessScopedName(base_desktop_name), "Exec", &exec_value)); 148 GetServiceProcessScopedName(base_desktop_name), "Exec", &exec_value));
150 #endif // defined(OS_WIN) 149 #endif // defined(OS_WIN)
151 } 150 }
152 151
153 TEST_F(ServiceProcessStateTest, SharedMem) { 152 TEST_F(ServiceProcessStateTest, SharedMem) {
154 std::string version; 153 std::string version;
155 base::ProcessId pid; 154 base::ProcessId pid;
156 #if defined(OS_WIN) 155 #if defined(OS_WIN)
157 // On Posix, named shared memory uses a file on disk. This file 156 // On Posix, named shared memory uses a file on disk. This file
158 // could be lying around from previous crashes which could cause 157 // could be lying around from previous crashes which could cause
159 // GetServiceProcessPid to lie. On Windows, we use a named event so we 158 // GetServiceProcessPid to lie. On Windows, we use a named event so we
160 // don't have this issue. Until we have a more stable shared memory 159 // don't have this issue. Until we have a more stable shared memory
161 // implementation on Posix, this check will only execute on Windows. 160 // implementation on Posix, this check will only execute on Windows.
162 ASSERT_FALSE(GetServiceProcessData(&version, &pid)); 161 ASSERT_FALSE(GetServiceProcessData(&version, &pid));
163 #endif // defined(OS_WIN) 162 #endif // defined(OS_WIN)
164 ServiceProcessState* state = ServiceProcessState::GetInstance(); 163 ServiceProcessState state;
165 ASSERT_TRUE(state->Initialize()); 164 ASSERT_TRUE(state.Initialize());
166 ASSERT_TRUE(GetServiceProcessData(&version, &pid)); 165 ASSERT_TRUE(GetServiceProcessData(&version, &pid));
167 ASSERT_EQ(base::GetCurrentProcId(), pid); 166 ASSERT_EQ(base::GetCurrentProcId(), pid);
168 } 167 }
169 168
170 TEST_F(ServiceProcessStateTest, ForceShutdown) { 169 TEST_F(ServiceProcessStateTest, ForceShutdown) {
171 base::ProcessHandle handle = SpawnChild("ServiceProcessStateTestShutdown", 170 base::ProcessHandle handle = SpawnChild("ServiceProcessStateTestShutdown",
172 true); 171 true);
173 ASSERT_TRUE(handle); 172 ASSERT_TRUE(handle);
174 for (int i = 0; !CheckServiceProcessReady() && i < 10; ++i) { 173 for (int i = 0; !CheckServiceProcessReady() && i < 10; ++i) {
175 base::PlatformThread::Sleep(TestTimeouts::tiny_timeout_ms()); 174 base::PlatformThread::Sleep(TestTimeouts::tiny_timeout_ms());
176 } 175 }
177 ASSERT_TRUE(CheckServiceProcessReady()); 176 ASSERT_TRUE(CheckServiceProcessReady());
178 std::string version; 177 std::string version;
179 base::ProcessId pid; 178 base::ProcessId pid;
180 ASSERT_TRUE(GetServiceProcessData(&version, &pid)); 179 ASSERT_TRUE(GetServiceProcessData(&version, &pid));
181 ASSERT_TRUE(ForceServiceProcessShutdown(version, pid)); 180 ASSERT_TRUE(ForceServiceProcessShutdown(version, pid));
182 int exit_code = 0; 181 int exit_code = 0;
183 ASSERT_TRUE(base::WaitForExitCodeWithTimeout(handle, 182 ASSERT_TRUE(base::WaitForExitCodeWithTimeout(handle,
184 &exit_code, TestTimeouts::action_timeout_ms() * 2)); 183 &exit_code, TestTimeouts::action_timeout_ms() * 2));
185 ASSERT_EQ(exit_code, 0); 184 ASSERT_EQ(exit_code, 0);
186 } 185 }
187 186
188 MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestSingleton) { 187 MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestSingleton) {
189 ServiceProcessState* state = ServiceProcessState::GetInstance(); 188 ServiceProcessState state;
190 EXPECT_FALSE(state->Initialize()); 189 EXPECT_FALSE(state.Initialize());
191 return 0; 190 return 0;
192 } 191 }
193 192
194 MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestReadyTrue) { 193 MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestReadyTrue) {
195 EXPECT_TRUE(CheckServiceProcessReady()); 194 EXPECT_TRUE(CheckServiceProcessReady());
196 return 0; 195 return 0;
197 } 196 }
198 197
199 MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestReadyFalse) { 198 MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestReadyFalse) {
200 EXPECT_FALSE(CheckServiceProcessReady()); 199 EXPECT_FALSE(CheckServiceProcessReady());
201 return 0; 200 return 0;
202 } 201 }
203 202
204 MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestShutdown) { 203 MULTIPROCESS_TEST_MAIN(ServiceProcessStateTestShutdown) {
205 MessageLoop message_loop; 204 MessageLoop message_loop;
206 message_loop.set_thread_name("ServiceProcessStateTestShutdownMainThread"); 205 message_loop.set_thread_name("ServiceProcessStateTestShutdownMainThread");
207 base::Thread io_thread_("ServiceProcessStateTestShutdownIOThread"); 206 base::Thread io_thread_("ServiceProcessStateTestShutdownIOThread");
208 base::Thread::Options options(MessageLoop::TYPE_IO, 0); 207 base::Thread::Options options(MessageLoop::TYPE_IO, 0);
209 EXPECT_TRUE(io_thread_.StartWithOptions(options)); 208 EXPECT_TRUE(io_thread_.StartWithOptions(options));
210 ServiceProcessState* state = ServiceProcessState::GetInstance(); 209 ServiceProcessState state;
211 EXPECT_TRUE(state->Initialize()); 210 EXPECT_TRUE(state.Initialize());
212 EXPECT_TRUE(state->SignalReady(io_thread_.message_loop_proxy(), 211 EXPECT_TRUE(state.SignalReady(io_thread_.message_loop_proxy(),
213 NewRunnableFunction(&ShutdownTask, 212 NewRunnableFunction(&ShutdownTask,
214 MessageLoop::current()))); 213 MessageLoop::current())));
215 message_loop.PostDelayedTask(FROM_HERE, 214 message_loop.PostDelayedTask(FROM_HERE,
216 new MessageLoop::QuitTask(), 215 new MessageLoop::QuitTask(),
217 TestTimeouts::action_max_timeout_ms()); 216 TestTimeouts::action_max_timeout_ms());
218 EXPECT_FALSE(g_good_shutdown); 217 EXPECT_FALSE(g_good_shutdown);
219 message_loop.Run(); 218 message_loop.Run();
220 EXPECT_TRUE(g_good_shutdown); 219 EXPECT_TRUE(g_good_shutdown);
221 return 0; 220 return 0;
222 } 221 }
223 222
223 #else // !OS_MACOSX
224
225 #include <CoreFoundation/CoreFoundation.h>
226
227 #include <launch.h>
228 #include <sys/stat.h>
229
230 #include "base/file_path.h"
231 #include "base/file_util.h"
232 #include "base/mac/mac_util.h"
233 #include "base/mac/scoped_cftyperef.h"
234 #include "base/message_loop.h"
235 #include "base/scoped_temp_dir.h"
236 #include "base/stringprintf.h"
237 #include "base/sys_string_conversions.h"
238 #include "base/test/test_timeouts.h"
239 #include "base/threading/thread.h"
240 #include "chrome/common/launchd_mac.h"
241 #include "testing/gtest/include/gtest/gtest.h"
242
243 // TODO(dmaclach): Write this in terms of a real mock.
244 // http://crbug.com/76923
245 class MockLaunchd : public Launchd {
246 public:
247 MockLaunchd(const FilePath& file, MessageLoop* loop)
248 : file_(file),
249 message_loop_(loop),
250 restart_called_(false),
251 remove_called_(false),
252 checkin_called_(false),
253 write_called_(false),
254 delete_called_(false)
Mark Mentovai 2011/03/22 00:48:24 Nit: { goes on this line.
dmac 2011/03/22 03:13:32 Done.
255 { }
256 virtual ~MockLaunchd() { }
257
258 virtual CFDictionaryRef CopyExports() OVERRIDE {
259 ADD_FAILURE();
260 return NULL;
261 }
262
263 virtual CFDictionaryRef CopyJobDictionary(CFStringRef label) OVERRIDE {
264 ADD_FAILURE();
265 return NULL;
266 }
267
268 virtual CFDictionaryRef CopyDictionaryByCheckingIn(CFErrorRef* error)
269 OVERRIDE {
270 checkin_called_ = true;
271 CFStringRef program = CFSTR(LAUNCH_JOBKEY_PROGRAM);
272 CFStringRef program_args = CFSTR(LAUNCH_JOBKEY_PROGRAMARGUMENTS);
273 const void *keys[] = { program, program_args };
274 base::mac::ScopedCFTypeRef<CFStringRef> path(
275 base::SysUTF8ToCFStringRef(file_.value()));
276 const void *array_values[] = { path.get() };
277 base::mac::ScopedCFTypeRef<CFArrayRef> args(
278 CFArrayCreate(kCFAllocatorDefault,
279 array_values,
280 1,
281 &kCFTypeArrayCallBacks));
282 const void *values[] = { path, args };
283 return CFDictionaryCreate(kCFAllocatorDefault,
284 keys,
285 values,
286 arraysize(keys),
287 &kCFTypeDictionaryKeyCallBacks,
288 &kCFTypeDictionaryValueCallBacks);
289 }
290
291 virtual bool RemoveJob(CFStringRef label, CFErrorRef* error) OVERRIDE {
292 remove_called_ = true;
293 message_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask);
294 return true;
295 }
296
297 virtual bool RestartJob(Domain domain,
298 Type type,
299 CFStringRef name,
300 CFStringRef session_type) OVERRIDE {
301 restart_called_ = true;
302 message_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask);
303 return true;
304 }
305
306 virtual CFMutableDictionaryRef CreatePlistFromFile(
307 Domain domain,
308 Type type,
309 CFStringRef name) OVERRIDE {
310 base::mac::ScopedCFTypeRef<CFDictionaryRef> dict(
311 CopyDictionaryByCheckingIn(NULL));
312 return CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, dict);
313 }
314
315 virtual bool WritePlistToFile(Domain domain,
316 Type type,
317 CFStringRef name,
318 CFDictionaryRef dict) OVERRIDE {
319 write_called_ = true;
320 return true;
321 }
322
323 virtual bool DeletePlist(Domain domain,
324 Type type,
325 CFStringRef name) OVERRIDE {
326 delete_called_ = true;
327 return true;
328 }
329
330 FilePath file_;
Mark Mentovai 2011/03/22 00:48:24 OK for now, but the data should really be in a pri
dmac 2011/03/22 03:13:32 Done.
331 MessageLoop* message_loop_;
332 bool restart_called_;
333 bool remove_called_;
334 bool checkin_called_;
335 bool write_called_;
336 bool delete_called_;
337 };
338
339 class ServiceProcessStateFileManipulationTest : public ::testing::Test {
340 protected:
341 ServiceProcessStateFileManipulationTest()
342 : io_thread_("ServiceProcessStateFileManipulationTest_IO") {
343 }
344 virtual ~ServiceProcessStateFileManipulationTest() { }
345
346 virtual void SetUp() {
347 base::Thread::Options options;
348 options.message_loop_type = MessageLoop::TYPE_IO;
349 ASSERT_TRUE(io_thread_.StartWithOptions(options));
350 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
351 ASSERT_TRUE(MakeABundle(temp_dir_.path(),
352 "Test",
353 &bundle_path_,
354 &executable_path_));
355 mock_launchd_.reset(new MockLaunchd(executable_path_, &loop_));
356 scoped_launchd_instance_.reset(
357 new Launchd::ScopedInstance(mock_launchd_.get()));
358 ASSERT_TRUE(service_process_state_.Initialize());
359 ASSERT_TRUE(service_process_state_.SignalReady(
360 io_thread_.message_loop_proxy(),
361 NULL));
362 loop_.PostDelayedTask(FROM_HERE,
363 new MessageLoop::QuitTask,
364 TestTimeouts::large_test_timeout_ms());
365 }
366
367 bool MakeABundle(const FilePath& dst,
368 const std::string& name,
369 FilePath* bundle_root,
370 FilePath* executable) {
371 *bundle_root = dst.Append(name + std::string(".app"));
372 FilePath contents = bundle_root->AppendASCII("Contents");
373 FilePath mac_os = contents.AppendASCII("MacOS");
374 *executable = mac_os.Append(name);
375 FilePath info_plist = contents.Append("Info.plist");
376
377 if (!file_util::CreateDirectory(mac_os)) {
378 return false;
379 }
380 const char *data = "#! testbundle";
Mark Mentovai 2011/03/22 00:48:24 Put a \n at the end of this string.
dmac 2011/03/22 03:13:32 Done.
381 int len = strlen(data);
382 if (file_util::WriteFile(*executable, data, len) != len) {
383 return false;
384 }
385 if (chmod(executable->value().c_str(), 0555) != 0) {
386 return false;
387 }
388
389 const char* info_plist_format =
390 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r"
Mark Mentovai 2011/03/22 00:48:24 Your lines should end with \n throughout this stri
dmac 2011/03/22 03:13:32 I'm a classy kind of guy. Done.
391 "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple .com/DTDs/PropertyList-1.0.dtd\">\r"
392 "<plist version=\"1.0\">\r"
393 "<dict>\r"
394 " <key>CFBundleDevelopmentRegion</key>\r"
395 " <string>English</string>\r"
396 " <key>CFBundleIdentifier</key>\r"
397 " <string>com.test.%s</string>\r"
398 " <key>CFBundleInfoDictionaryVersion</key>\r"
399 " <string>6.0</string>\r"
400 " <key>CFBundleExecutable</key>\r"
401 " <string>%s</string>\r"
402 " <key>CFBundleVersion</key>\r"
403 " <string>1</string>\r"
404 "</dict>\r"
405 "</plist>\r";
406 std::string info_plist_data = base::StringPrintf(info_plist_format,
407 name.c_str(),
408 name.c_str());
409 len = info_plist_data.length();
410 if (file_util::WriteFile(info_plist, info_plist_data.c_str(), len) != len) {
411 return false;
412 }
413 const UInt8* bundle_root_path =
414 reinterpret_cast<const UInt8*>(bundle_root->value().c_str());
415 base::mac::ScopedCFTypeRef<CFURLRef> url(
416 CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
417 bundle_root_path,
418 bundle_root->value().length(),
419 true));
420 base::mac::ScopedCFTypeRef<CFBundleRef> bundle(
421 CFBundleCreate(kCFAllocatorDefault, url));
422 return bundle.get();
423 }
424
425 ScopedTempDir temp_dir_;
Mark Mentovai 2011/03/22 00:48:24 Make private when able, as in the class above.
dmac 2011/03/22 03:13:32 Done.
426 MessageLoopForUI loop_;
427 base::Thread io_thread_;
428 FilePath executable_path_, bundle_path_;
429 scoped_ptr<MockLaunchd> mock_launchd_;
430 scoped_ptr<Launchd::ScopedInstance> scoped_launchd_instance_;
431 ServiceProcessState service_process_state_;
432 };
433
434 void DeleteFunc(const FilePath& file) {
435 EXPECT_TRUE(file_util::Delete(file, true));
436 }
437
438 void MoveFunc(const FilePath& from, const FilePath& to) {
439 EXPECT_TRUE(file_util::Move(from, to));
440 }
441
442 void ChangeAttr(const FilePath& from, int mode) {
443 EXPECT_EQ(chmod(from.value().c_str(), mode), 0);
444 }
445
446 class ScopedAttributesRestorer {
447 public:
448 ScopedAttributesRestorer(const FilePath& path, int mode)
449 : path_(path), mode_(mode) {
450 }
451 ~ScopedAttributesRestorer() {
452 ChangeAttr(path_, mode_);
453 }
454 private:
455 FilePath path_;
456 int mode_;
457 };
458
459 void TrashFunc(const FilePath& src) {
460 FSRef path_ref;
461 FSRef new_path_ref;
462 EXPECT_TRUE(base::mac::FSRefFromPath(src.value(), &path_ref));
463 OSStatus status = FSMoveObjectToTrashSync(&path_ref,
464 &new_path_ref,
465 kFSFileOperationDefaultOptions);
466 EXPECT_EQ(status, noErr) << "FSMoveObjectToTrashSync " << status;
467 }
468
469 TEST_F(ServiceProcessStateFileManipulationTest, DeleteFile) {
470 io_thread_.message_loop_proxy()->PostTask(
471 FROM_HERE,
472 NewRunnableFunction(&DeleteFunc, executable_path_));
473 loop_.Run();
474 ASSERT_TRUE(mock_launchd_->remove_called_);
475 ASSERT_TRUE(mock_launchd_->delete_called_);
476 }
477
478 TEST_F(ServiceProcessStateFileManipulationTest, DeleteBundle) {
479 io_thread_.message_loop_proxy()->PostTask(
480 FROM_HERE,
481 NewRunnableFunction(&DeleteFunc, bundle_path_));
482 loop_.Run();
483 ASSERT_TRUE(mock_launchd_->remove_called_);
484 ASSERT_TRUE(mock_launchd_->delete_called_);
485 }
486
487 TEST_F(ServiceProcessStateFileManipulationTest, MoveBundle) {
488 FilePath new_loc = temp_dir_.path().AppendASCII("MoveBundle");
489 io_thread_.message_loop_proxy()->PostTask(
490 FROM_HERE,
491 NewRunnableFunction(&MoveFunc, bundle_path_, new_loc));
492 loop_.Run();
493 ASSERT_TRUE(mock_launchd_->restart_called_);
494 ASSERT_TRUE(mock_launchd_->write_called_);
495 }
496
497 TEST_F(ServiceProcessStateFileManipulationTest, MoveFile) {
498 FilePath new_loc = temp_dir_.path().AppendASCII("MoveFile");
499 io_thread_.message_loop_proxy()->PostTask(
500 FROM_HERE,
501 NewRunnableFunction(&MoveFunc, executable_path_, new_loc));
502 loop_.Run();
503 ASSERT_TRUE(mock_launchd_->remove_called_);
504 ASSERT_TRUE(mock_launchd_->delete_called_);
505 }
506
507 TEST_F(ServiceProcessStateFileManipulationTest, TrashBundle) {
508 FSRef bundle_ref;
509 ASSERT_TRUE(base::mac::FSRefFromPath(bundle_path_.value(), &bundle_ref));
510 io_thread_.message_loop_proxy()->PostTask(
511 FROM_HERE,
512 NewRunnableFunction(&TrashFunc, bundle_path_));
513 loop_.Run();
514 ASSERT_TRUE(mock_launchd_->remove_called_);
515 ASSERT_TRUE(mock_launchd_->delete_called_);
516 std::string path(base::mac::PathFromFSRef(bundle_ref));
517 FilePath file_path(path);
518 ASSERT_TRUE(file_util::Delete(file_path, true));
519 }
520
521 TEST_F(ServiceProcessStateFileManipulationTest, ChangeAttr) {
522 ScopedAttributesRestorer restorer(bundle_path_, 0777);
523 io_thread_.message_loop_proxy()->PostTask(
524 FROM_HERE,
525 NewRunnableFunction(&ChangeAttr, bundle_path_, 0222));
526 loop_.Run();
527 ASSERT_TRUE(mock_launchd_->remove_called_);
528 ASSERT_TRUE(mock_launchd_->delete_called_);
529 }
530
224 #endif // !OS_MACOSX 531 #endif // !OS_MACOSX
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698