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. 4 5#ifndef CONTENT_COMMON_SANDBOX_MAC_UNITTEST_HELPER_H_ 6#define CONTENT_COMMON_SANDBOX_MAC_UNITTEST_HELPER_H_ 7 8#include "base/test/multiprocess_test.h" 9#include "content/common/sandbox_mac.h" 10 11namespace content { 12 13// Helpers for writing unit tests that runs in the context of the Mac sandbox. 14// 15// How to write a sandboxed test: 16// 1. Create a class that inherits from MacSandboxTestCase and overrides 17// its functions to run code before or after the sandbox is initialised in a 18// subprocess. 19// 2. Register the class you just created with the REGISTER_SANDBOX_TEST_CASE() 20// macro. 21// 3. Write a test [using TEST_F()] that inherits from MacSandboxTest and call 22// one of its helper functions to launch the test. 23// 24// Example: 25// class TestCaseThatRunsInSandboxedSubprocess : public MacSandboxTestCase { 26// public: 27// virtual bool SandboxedTest() { 28// .. test code that runs in sandbox goes here .. 29// return true; // always succeed. 30// } 31// }; 32// 33// // Register the test case you just created. 34// REGISTER_SANDBOX_TEST_CASE(TestCaseThatRunsInSandboxedSubprocess); 35// 36// TEST_F(MacSandboxTest, ATest) { 37// EXPECT_TRUE(RunTestInAllSandboxTypes( 38// "TestCaseThatRunsInSandboxedSubprocess", 39// NULL)); 40// } 41 42// Base test type with helper functions to spawn a subprocess that exercises 43// a given test in the sandbox. 44class MacSandboxTest : public base::MultiProcessTest { 45 public: 46 // Runs a test specified by |test_name| in a sandbox of the type specified 47 // by |sandbox_type|. |test_data| is a custom string that a test can pass 48 // to the child process runing in the sandbox, or NULL if additional data is 49 // required. 50 // Returns true if the test passes, false if either of the functions in 51 // the corresponding MacSandboxTestCase return false. 52 bool RunTestInSandbox(content::SandboxType sandbox_type, 53 const char* test_name, 54 const char* test_data); 55 56 // Runs the test specified by |test_name| in all the different sandbox types 57 // known to content, one by one. 58 // Returns true if the test passes, false if either of the functions in 59 // the corresponding MacSandboxTestCase return false in any of the spawned 60 // processes. 61 // 62 // DANGER DANGER DANGER: 63 // Additional sandbox types defined by the embedder (e.g. the NaCl sandbox) 64 // won't be covered by these tests. 65 bool RunTestInAllSandboxTypes(const char* test_name, 66 const char* test_data); 67}; 68 69// Class to ease writing test cases that run inside the OS X sandbox. 70// This class is instantiated in a subprocess, and allows you to run test code 71// at various stages of execution. 72// Note that you must register the subclass you create with the 73// REGISTER_SANDBOX_TEST_CASE so it's visible to the test driver. 74class MacSandboxTestCase { 75 public: 76 virtual ~MacSandboxTestCase() {} 77 78 // Code that runs in the sandboxed subprocess before the sandbox is 79 // initialized. 80 // Returning false from this function will cause the entire test case to fail. 81 virtual bool BeforeSandboxInit(); 82 83 // Code that runs in the sandboxed subprocess when the sandbox has been 84 // enabled. 85 // Returning false from this function will cause the entire test case to fail. 86 virtual bool SandboxedTest() = 0; 87 88 // The data that's passed in the |user_data| parameter of 89 // RunTest[s]InSandbox() is passed to this function. 90 virtual void SetTestData(const char* test_data); 91 92 protected: 93 std::string test_data_; 94}; 95 96// Plumbing to support the REGISTER_SANDBOX_TEST_CASE macro. 97namespace internal { 98 99// Register a test case with a given name. 100void AddSandboxTestCase(const char* test_name, MacSandboxTestCase* test_class); 101 102// Construction of this class causes a new entry to be placed in a global 103// map. 104template <class T> struct RegisterSandboxTest { 105 RegisterSandboxTest(const char* test_name) { 106 AddSandboxTestCase(test_name, new T); 107 } 108}; 109 110#define REGISTER_SANDBOX_TEST_CASE(class_name) \ 111 namespace { \ 112 content::internal::RegisterSandboxTest<class_name> \ 113 register_test##class_name(#class_name); \ 114 } // namespace 115 116} // namespace internal 117 118} // namespace content 119 120#endif // CONTENT_COMMON_SANDBOX_MAC_UNITTEST_HELPER_H_ 121