Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2009 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 #ifndef BASE_MULTIPROCESS_TEST_H_
      6 #define BASE_MULTIPROCESS_TEST_H_
      7 
      8 #include "base/base_switches.h"
      9 #include "base/command_line.h"
     10 #include "base/process_util.h"
     11 #include "base/string_util.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 #include "testing/multiprocess_func_list.h"
     14 #include "testing/platform_test.h"
     15 
     16 #if defined(OS_POSIX)
     17 #include <sys/types.h>
     18 #include <unistd.h>
     19 #endif
     20 
     21 // Command line switch to invoke a child process rather than
     22 // to run the normal test suite.
     23 static const char kRunClientProcess[] = "client";
     24 
     25 // A MultiProcessTest is a test class which makes it easier to
     26 // write a test which requires code running out of process.
     27 //
     28 // To create a multiprocess test simply follow these steps:
     29 //
     30 // 1) Derive your test from MultiProcessTest. Example:
     31 //
     32 //    class MyTest : public MultiProcessTest {
     33 //    };
     34 //
     35 //    TEST_F(MyTest, TestCaseName) {
     36 //      ...
     37 //    }
     38 //
     39 // 2) Create a mainline function for the child processes and include
     40 //    testing/multiprocess_func_list.h.
     41 //    See the declaration of the MULTIPROCESS_TEST_MAIN macro
     42 //    in that file for an example.
     43 // 3) Call SpawnChild(L"foo"), where "foo" is the name of
     44 //    the function you wish to run in the child processes.
     45 // That's it!
     46 //
     47 class MultiProcessTest : public PlatformTest {
     48  protected:
     49   // Run a child process.
     50   // 'procname' is the name of a function which the child will
     51   // execute.  It must be exported from this library in order to
     52   // run.
     53   //
     54   // Example signature:
     55   //    extern "C" int __declspec(dllexport) FooBar() {
     56   //         // do client work here
     57   //    }
     58   //
     59   // Returns the handle to the child, or NULL on failure
     60   //
     61   // TODO(darin): re-enable this once we have base/debug_util.h
     62   // ProcessDebugFlags(&cl, DebugUtil::UNKNOWN, false);
     63   base::ProcessHandle SpawnChild(const std::wstring& procname) {
     64     return SpawnChild(procname, false);
     65   }
     66 
     67   base::ProcessHandle SpawnChild(const std::wstring& procname,
     68                                  bool debug_on_start) {
     69 #if defined(OS_WIN)
     70     return SpawnChildImpl(procname, debug_on_start);
     71 #elif defined(OS_POSIX)
     72     base::file_handle_mapping_vector empty_file_list;
     73     return SpawnChildImpl(procname, empty_file_list, debug_on_start);
     74 #endif
     75   }
     76 
     77 #if defined(OS_POSIX)
     78   base::ProcessHandle SpawnChild(
     79       const std::wstring& procname,
     80       const base::file_handle_mapping_vector& fds_to_map,
     81       bool debug_on_start) {
     82     return SpawnChildImpl(procname, fds_to_map, debug_on_start);
     83   }
     84 #endif
     85 
     86 protected:
     87   CommandLine MakeCmdLine(const std::wstring& procname, bool debug_on_start) {
     88     CommandLine cl(*CommandLine::ForCurrentProcess());
     89     cl.AppendSwitchWithValue(kRunClientProcess, procname);
     90     if (debug_on_start)
     91       cl.AppendSwitch(switches::kDebugOnStart);
     92     return cl;
     93   }
     94 
     95  private:
     96 #if defined(OS_WIN)
     97   base::ProcessHandle SpawnChildImpl(const std::wstring& procname,
     98                                      bool debug_on_start) {
     99     base::ProcessHandle handle = static_cast<base::ProcessHandle>(NULL);
    100     base::LaunchApp(MakeCmdLine(procname, debug_on_start),
    101                     false, true, &handle);
    102     return handle;
    103   }
    104 
    105 #elif defined(OS_POSIX)
    106   // TODO(port): with the CommandLine refactoring, this code is very similar
    107   // to the Windows code.  Investigate whether this can be made shorter.
    108   base::ProcessHandle SpawnChildImpl(
    109       const std::wstring& procname,
    110       const base::file_handle_mapping_vector& fds_to_map,
    111       bool debug_on_start) {
    112     base::ProcessHandle handle = base::kNullProcessHandle;
    113     base::LaunchApp(MakeCmdLine(procname, debug_on_start).argv(),
    114                     fds_to_map, false, &handle);
    115     return handle;
    116   }
    117 #endif
    118 };
    119 
    120 #endif  // BASE_MULTIPROCESS_TEST_H_
    121