1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/common/sandbox_mac_unittest_helper.h"
extern "C" {
#include <sandbox.h>
}
#include <map>
#include "base/file_path.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "chrome/common/sandbox_mac.h"
#include "testing/multiprocess_func_list.h"
using sandbox::Sandbox;
namespace {
const char* kSandboxTypeKey = "CHROMIUM_SANDBOX_SANDBOX_TYPE";
const char* kSandboxTestNameKey = "CHROMIUM_SANDBOX_TEST_NAME";
const char* kTestDataKey = "CHROMIUM_SANDBOX_USER_DATA";
} // namespace
namespace sandboxtest {
// Support infrastructure for REGISTER_SANDBOX_TEST_CASE macro.
namespace internal {
typedef std::map<std::string,MacSandboxTestCase*> SandboxTestMap;
// A function that returns a common map from string -> test case class.
SandboxTestMap& GetSandboxTestMap() {
static SandboxTestMap test_map;
return test_map;
}
void AddSandboxTestCase(const char* test_name, MacSandboxTestCase* test_class) {
SandboxTestMap& test_map = GetSandboxTestMap();
if (test_map.find(test_name) != test_map.end()) {
LOG(ERROR) << "Trying to register duplicate test" << test_name;
NOTREACHED();
}
test_map[test_name] = test_class;
}
} // namespace internal
bool MacSandboxTest::RunTestInAllSandboxTypes(const char* test_name,
const char* test_data) {
// Go through all the sandbox types, and run the test case in each of them
// if one fails, abort.
for(int i = static_cast<int>(Sandbox::SANDBOX_TYPE_FIRST_TYPE);
i < Sandbox::SANDBOX_AFTER_TYPE_LAST_TYPE;
++i) {
if (!RunTestInSandbox(static_cast<Sandbox::SandboxProcessType>(i),
test_name, test_data)) {
LOG(ERROR) << "Sandboxed test (" << test_name << ")" <<
"Failed in sandbox type " << i <<
"user data: (" << test_data << ")";
return false;
}
}
return true;
}
bool MacSandboxTest::RunTestInSandbox(Sandbox::SandboxProcessType sandbox_type,
const char* test_name,
const char* test_data) {
std::stringstream s;
s << static_cast<int>(static_cast<int>(sandbox_type));
setenv(kSandboxTypeKey, s.str().c_str(), 1);
setenv(kSandboxTestNameKey, test_name, 1);
if (test_data)
setenv(kTestDataKey, test_data, 1);
base::ProcessHandle child_process = SpawnChild("mac_sandbox_test_runner",
false);
int code = -1;
if (!base::WaitForExitCode(child_process, &code)) {
LOG(WARNING) << "base::WaitForExitCode failed";
return false;
}
return code == 0;
}
// Given a test name specified by |name| return that test case.
// If no test case is found for the given name, return NULL.
MacSandboxTestCase *SandboxTestForName(const char* name) {
using internal::SandboxTestMap;
using internal::GetSandboxTestMap;
SandboxTestMap all_tests = GetSandboxTestMap();
SandboxTestMap::iterator it = all_tests.find(name);
if (it == all_tests.end()) {
LOG(ERROR) << "Couldn't find sandbox test case(" << name << ")";
return NULL;
}
return it->second;
}
} // namespace sandboxtest
namespace {
// Main function for driver process that enables the sandbox and runs test
// code.
MULTIPROCESS_TEST_MAIN(mac_sandbox_test_runner) {
// Extract parameters.
char* sandbox_type_str = getenv(kSandboxTypeKey);
if (!sandbox_type_str) {
LOG(ERROR) << "Sandbox type not specified";
return -1;
}
Sandbox::SandboxProcessType sandbox_type =
static_cast<Sandbox::SandboxProcessType>(atoi(sandbox_type_str));
char* sandbox_test_name = getenv(kSandboxTestNameKey);
if (!sandbox_test_name) {
LOG(ERROR) << "Sandbox test name not specified";
return -1;
}
const char* test_data = getenv(kTestDataKey);
// Find Test Function to run;
scoped_ptr<sandboxtest::MacSandboxTestCase>
test_case(sandboxtest::SandboxTestForName(sandbox_test_name));
if (!test_case.get()) {
LOG(ERROR) << "Invalid sandbox test name (" << sandbox_test_name << ")";
return -1;
}
test_case->SetTestData(test_data);
// Run Test.
if (!test_case->BeforeSandboxInit()) {
LOG(ERROR) << sandbox_test_name << "Failed test before sandbox init";
return -1;
}
Sandbox::SandboxWarmup(sandbox_type);
if (!Sandbox::EnableSandbox(sandbox_type, FilePath())) {
LOG(ERROR) << "Failed to initialize sandbox " << sandbox_type;
return -1;
}
if (!test_case->SandboxedTest()) {
LOG(ERROR) << sandbox_test_name << "Failed sandboxed test";
return -1;
}
return 0;
}
} // namespace
|