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

Side by Side Diff: base/zygote_manager_unittest.cc

Issue 115773: Prototype implementation of zygotes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 6 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
« no previous file with comments | « base/zygote_manager.cc ('k') | chrome/app/breakpad_linux.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 #include "base/zygote_manager.h"
6
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <stdlib.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12
13 #include "base/eintr_wrapper.h"
14 #include "base/file_path.h"
15 #include "base/file_util.h"
16 #include "base/process_util.h"
17 #include "base/scoped_ptr.h"
18 #include "base/string_util.h"
19
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 using file_util::Delete;
23 using file_util::WriteFile;
24 using file_util::ReadFileToString;
25 using file_util::GetCurrentDirectory;
26
27 #if defined(OS_LINUX)
28 // ZygoteManager is only used on Linux at the moment
29
30 typedef testing::Test ZygoteManagerTest;
31
32 TEST_F(ZygoteManagerTest, Ping) {
33 base::ZygoteManager zm;
34
35 scoped_ptr< std::vector<std::string> > new_argv;
36 new_argv.reset(zm.Start());
37 EXPECT_TRUE(new_argv.get() == NULL);
38 // Measure round trip time
39 base::TimeDelta delta;
40 EXPECT_EQ(zm.Ping(&delta), true);
41 EXPECT_LT(delta.InMilliseconds(), 5000);
42 }
43
44 TEST_F(ZygoteManagerTest, SpawnChild) {
45 base::ZygoteManager zm;
46 const int kDummyChildExitCode = 39;
47
48 scoped_ptr< std::vector<std::string> > new_argv;
49 new_argv.reset(zm.Start());
50 if (new_argv.get() == NULL) {
51 // original process
52 // Launch a child process
53 std::vector<std::string> myargs;
54 myargs.push_back(std::string("0thArg"));
55 myargs.push_back(std::string("1stArg"));
56 base::file_handle_mapping_vector no_files;
57 pid_t child = zm.LongFork(myargs, no_files);
58 EXPECT_NE(child, -1);
59 EXPECT_NE(child, 0);
60 LOG(INFO) << "child pid " << child;
61
62 // ZygoteManager doesn't support waiting for exit status
63 int status;
64 int err = HANDLE_EINTR(waitpid(child, &status, 0));
65 EXPECT_EQ(-1, err);
66 EXPECT_EQ(ECHILD, errno);
67 } else {
68 LOG(INFO) << "Hello from child!";
69 // child process
70 std::string arg0(new_argv.get()->at(0));
71 std::string arg1(new_argv.get()->at(1));
72 EXPECT_EQ(arg0, std::string("0thArg"));
73 EXPECT_EQ(arg1, std::string("1stArg"));
74 exit(kDummyChildExitCode);
75 }
76 }
77
78 TEST_F(ZygoteManagerTest, MapFile) {
79 base::ZygoteManager zm;
80 const int kDummyChildExitCode = 39;
81 const int kSpecialFDSlot = 5;
82
83 scoped_ptr< std::vector<std::string> > new_argv;
84 new_argv.reset(zm.Start());
85 if (new_argv.get() == NULL) {
86 // original process
87 // Launch a child process
88 std::vector<std::string> myargs;
89 myargs.push_back(std::string("0thArg"));
90 myargs.push_back(std::string("1stArg"));
91 base::file_handle_mapping_vector fds_to_map;
92 int fd = open("/tmp/zygote_manager_unittest.tmp", O_CREAT|O_RDWR|O_TRUNC, 06 44);
93 fds_to_map.push_back(std::pair<int, int>(fd, kSpecialFDSlot));
94 pid_t child = zm.LongFork(myargs, fds_to_map);
95 EXPECT_NE(child, -1);
96 EXPECT_NE(child, 0);
97 // FIXME: really wait for child
98 sleep(3);
99 char buf[100];
100
101 // Expect fd to be seeked to end, so reading without seeking should fail
102 off_t loc = lseek(fd, 0L, SEEK_CUR);
103 EXPECT_EQ(3, loc);
104
105 memset(buf, 0, sizeof(buf));
106 int nread = read(fd, buf, 5);
107 EXPECT_EQ(0, nread);
108
109 // Try again from beginning
110 lseek(fd, 0L, SEEK_SET);
111 memset(buf, 0, sizeof(buf));
112 nread = read(fd, buf, 2);
113 EXPECT_EQ(2, nread);
114 EXPECT_EQ(strncmp(buf, "hi", 2), 0);
115 close(fd);
116 } else {
117 // child process
118 // Write three bytes; this happens to seek the file descriptor to the end.
119 int nwritten = write(kSpecialFDSlot, "hi\n", 3);
120 EXPECT_EQ(3, nwritten);
121 exit(kDummyChildExitCode);
122 }
123 }
124
125 TEST_F(ZygoteManagerTest, OpenFile) {
126 base::ZygoteManager zm;
127
128 scoped_ptr< std::vector<std::string> > new_argv;
129 new_argv.reset(zm.Start());
130 EXPECT_EQ(NULL, new_argv.get());
131
132 const char kSomeText[] = "foobar\n";
133
134 // Verify that we disallow nonabsolute paths.
135 FilePath badfilepath(FilePath::kCurrentDirectory);
136 badfilepath = badfilepath.AppendASCII("zygote_manager_test.pak");
137 ASSERT_FALSE(badfilepath.IsAbsolute());
138 EXPECT_NE(-1, WriteFile(badfilepath, kSomeText, strlen(kSomeText)));
139 std::string badfilename = WideToASCII(badfilepath.ToWStringHack());
140 int fd = zm.OpenFile(badfilename);
141 EXPECT_EQ(-1, fd);
142 EXPECT_TRUE(Delete(badfilepath, false));
143
144 // Verify that we disallow non-plain files.
145 ASSERT_TRUE(GetCurrentDirectory(&badfilepath));
146 badfilepath = badfilepath.AppendASCII("zygote_manager_test.pak");
147 std::string badfilenameA = WideToASCII(badfilepath.ToWStringHack());
148 EXPECT_EQ(0, mkfifo(badfilenameA.c_str(), 0644));
149 badfilename = WideToASCII(badfilepath.ToWStringHack());
150 fd = zm.OpenFile(badfilename);
151 ASSERT_EQ(-1, fd);
152 EXPECT_TRUE(Delete(badfilepath, false));
153
154 // Verify that we disallow files not ending in .pak.
155 ASSERT_TRUE(GetCurrentDirectory(&badfilepath));
156 badfilepath = badfilepath.AppendASCII("zygote_manager_test.tmp");
157 ASSERT_NE(-1, WriteFile(badfilepath, kSomeText, strlen(kSomeText)));
158 badfilename = WideToASCII(badfilepath.ToWStringHack());
159 fd = zm.OpenFile(badfilename);
160 ASSERT_EQ(-1, fd);
161 EXPECT_TRUE(Delete(badfilepath, false));
162
163 // Verify that we disallow files in /etc
164 badfilepath = FilePath(FILE_PATH_LITERAL("/"));
165 badfilepath = badfilepath.AppendASCII("etc");
166 badfilepath = badfilepath.AppendASCII("hosts");
167 EXPECT_TRUE(badfilepath.IsAbsolute());
168 badfilename = WideToASCII(badfilepath.ToWStringHack());
169 fd = zm.OpenFile(badfilename);
170 ASSERT_EQ(-1, fd);
171
172 // Verify that we disallow files in /dev
173 badfilepath = FilePath(FILE_PATH_LITERAL("/"));
174 badfilepath = badfilepath.AppendASCII("dev");
175 badfilepath = badfilepath.AppendASCII("tty");
176 EXPECT_TRUE(badfilepath.IsAbsolute());
177 badfilename = WideToASCII(badfilepath.ToWStringHack());
178 fd = zm.OpenFile(badfilename);
179 ASSERT_EQ(-1, fd);
180
181 // Verify that we allow absolute paths with filename ending in .pak,
182 // and that we can open them a second time even if they were
183 // deleted after we opened them the first time.
184 // Because of our restrictive filename checks, can't put
185 // test file in /tmp, so put it in current directory.
186 FilePath goodfilepath;
187 ASSERT_TRUE(GetCurrentDirectory(&goodfilepath));
188 goodfilepath = goodfilepath.AppendASCII("zygote_manager_test.pak");
189 ASSERT_NE(-1, WriteFile(goodfilepath, kSomeText, strlen(kSomeText)));
190 std::string goodfilename = WideToASCII(goodfilepath.ToWStringHack());
191 for (int i = 0; i < 2; i++) {
192 fd = zm.OpenFile(goodfilename);
193 ASSERT_NE(-1, fd);
194 char buf[sizeof(kSomeText)];
195 // Can't use read because it depends on file position.
196 // (In practice these files are mmapped.)
197 int nread = pread(fd, buf, strlen(kSomeText), 0);
198 ASSERT_EQ(strlen(kSomeText), static_cast<size_t>(nread));
199 EXPECT_EQ(0, strncmp(buf, kSomeText, strlen(kSomeText)));
200 EXPECT_EQ(0, close(fd));
201
202 // oddly, our Delete returns true for nonexistant files.
203 EXPECT_EQ(true, Delete(goodfilepath, false));
204 }
205 }
206
207 TEST_F(ZygoteManagerTest, ChildOpenFile) {
208 base::ZygoteManager zm;
209 const int kDummyChildExitCode = 39;
210
211 const char kSomeText[] = "foobar\n";
212
213 FilePath resultfilepath(FILE_PATH_LITERAL("/tmp"));
214 resultfilepath = resultfilepath.AppendASCII("zygote_manager_test_result.tmp");
215 EXPECT_EQ(true, Delete(resultfilepath, false));
216
217 scoped_ptr< std::vector<std::string> > new_argv;
218 new_argv.reset(zm.Start());
219 if (new_argv.get() == NULL) {
220 // original process
221 // Launch a child process
222 std::vector<std::string> myargs;
223 base::file_handle_mapping_vector no_files;
224 pid_t child = zm.LongFork(myargs, no_files);
225 EXPECT_NE(child, -1);
226 EXPECT_NE(child, 0);
227 LOG(INFO) << "child pid " << child;
228
229 // Wait for resultfile to be created
230 std::string result;
231 int nloops = 0;
232 while (!ReadFileToString(resultfilepath, &result)) {
233 sleep(1);
234 ++nloops;
235 ASSERT_NE(10, nloops);
236 }
237 ASSERT_EQ(result, std::string(kSomeText));
238
239 EXPECT_EQ(true, Delete(resultfilepath, false));
240
241 } else {
242 LOG(INFO) << "Hello from child!";
243
244 FilePath goodfilepath;
245 ASSERT_TRUE(GetCurrentDirectory(&goodfilepath));
246 goodfilepath = goodfilepath.AppendASCII("zygote_manager_test.pak");
247 ASSERT_NE(-1, WriteFile(goodfilepath, kSomeText, strlen(kSomeText)));
248 std::string goodfilename = WideToASCII(goodfilepath.ToWStringHack());
249 int fd = zm.OpenFile(goodfilename);
250 EXPECT_EQ(true, Delete(goodfilepath, false));
251 ASSERT_NE(-1, fd);
252 char buf[sizeof(kSomeText)];
253 // Can't use read because it depends on file position.
254 // (In practice these files are mmapped.)
255 int nread = pread(fd, buf, strlen(kSomeText), 0);
256 ASSERT_EQ(strlen(kSomeText), static_cast<size_t>(nread));
257 EXPECT_EQ(0, strncmp(buf, kSomeText, strlen(kSomeText)));
258 EXPECT_EQ(0, close(fd));
259
260 ASSERT_NE(-1, WriteFile(resultfilepath, kSomeText, strlen(kSomeText)));
261
262 exit(kDummyChildExitCode);
263 }
264 }
265
266 #endif
OLDNEW
« no previous file with comments | « base/zygote_manager.cc ('k') | chrome/app/breakpad_linux.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698