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
3 // found in the LICENSE file.
5 #include "content/common/sandbox_mac_unittest_helper.h"
13 #include "base/files/file_path.h"
14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/process/kill.h"
17 #include "content/common/sandbox_mac.h"
18 #include "content/test/test_content_client.h"
19 #include "testing/multiprocess_func_list.h"
24 const char* kSandboxTypeKey = "CHROMIUM_SANDBOX_SANDBOX_TYPE";
25 const char* kSandboxTestNameKey = "CHROMIUM_SANDBOX_TEST_NAME";
26 const char* kTestDataKey = "CHROMIUM_SANDBOX_USER_DATA";
30 // Support infrastructure for REGISTER_SANDBOX_TEST_CASE macro.
33 typedef std::map<std::string,MacSandboxTestCase*> SandboxTestMap;
35 // A function that returns a common map from string -> test case class.
36 SandboxTestMap& GetSandboxTestMap() {
37 static SandboxTestMap test_map;
41 void AddSandboxTestCase(const char* test_name, MacSandboxTestCase* test_class) {
42 SandboxTestMap& test_map = GetSandboxTestMap();
43 if (test_map.find(test_name) != test_map.end()) {
44 LOG(ERROR) << "Trying to register duplicate test" << test_name;
47 test_map[test_name] = test_class;
50 } // namespace internal
52 bool MacSandboxTest::RunTestInAllSandboxTypes(const char* test_name,
53 const char* test_data) {
54 // Go through all the sandbox types, and run the test case in each of them
55 // if one fails, abort.
56 for(int i = static_cast<int>(SANDBOX_TYPE_FIRST_TYPE);
57 i < SANDBOX_TYPE_AFTER_LAST_TYPE;
59 if (!RunTestInSandbox(static_cast<SandboxType>(i),
60 test_name, test_data)) {
61 LOG(ERROR) << "Sandboxed test (" << test_name << ")" <<
62 "Failed in sandbox type " << i <<
63 "user data: (" << test_data << ")";
70 bool MacSandboxTest::RunTestInSandbox(SandboxType sandbox_type,
71 const char* test_name,
72 const char* test_data) {
74 s << static_cast<int>(static_cast<int>(sandbox_type));
75 setenv(kSandboxTypeKey, s.str().c_str(), 1);
76 setenv(kSandboxTestNameKey, test_name, 1);
78 setenv(kTestDataKey, test_data, 1);
80 base::ProcessHandle child_process = SpawnChild("mac_sandbox_test_runner");
81 if (child_process == base::kNullProcessHandle) {
82 LOG(WARNING) << "SpawnChild failed";
86 if (!base::WaitForExitCode(child_process, &code)) {
87 LOG(WARNING) << "base::WaitForExitCode failed";
93 bool MacSandboxTestCase::BeforeSandboxInit() {
97 void MacSandboxTestCase::SetTestData(const char* test_data) {
98 test_data_ = test_data;
101 // Given a test name specified by |name| return that test case.
102 // If no test case is found for the given name, return NULL.
103 MacSandboxTestCase *SandboxTestForName(const char* name) {
104 using internal::SandboxTestMap;
105 using internal::GetSandboxTestMap;
107 SandboxTestMap all_tests = GetSandboxTestMap();
109 SandboxTestMap::iterator it = all_tests.find(name);
110 if (it == all_tests.end()) {
111 LOG(ERROR) << "Couldn't find sandbox test case(" << name << ")";
118 // Main function for driver process that enables the sandbox and runs test
120 MULTIPROCESS_TEST_MAIN(mac_sandbox_test_runner) {
121 TestContentClient content_client;
122 SetContentClient(&content_client);
123 // Extract parameters.
124 char* sandbox_type_str = getenv(kSandboxTypeKey);
125 if (!sandbox_type_str) {
126 LOG(ERROR) << "Sandbox type not specified";
129 SandboxType sandbox_type = static_cast<SandboxType>(atoi(sandbox_type_str));
130 char* sandbox_test_name = getenv(kSandboxTestNameKey);
131 if (!sandbox_test_name) {
132 LOG(ERROR) << "Sandbox test name not specified";
136 const char* test_data = getenv(kTestDataKey);
138 // Find Test Function to run;
139 scoped_ptr<MacSandboxTestCase>
140 test_case(SandboxTestForName(sandbox_test_name));
142 LOG(ERROR) << "Invalid sandbox test name (" << sandbox_test_name << ")";
146 test_case->SetTestData(test_data);
149 if (!test_case->BeforeSandboxInit()) {
150 LOG(ERROR) << sandbox_test_name << "Failed test before sandbox init";
154 Sandbox::SandboxWarmup(sandbox_type);
156 if (!Sandbox::EnableSandbox(sandbox_type, base::FilePath())) {
157 LOG(ERROR) << "Failed to initialize sandbox " << sandbox_type;
161 if (!test_case->SandboxedTest()) {
162 LOG(ERROR) << sandbox_test_name << "Failed sandboxed test";
169 } // namespace content