Revision a4ccecf6 test/ganeti.utils_unittest.py
b/test/ganeti.utils_unittest.py | ||
---|---|---|
48 | 48 |
RunParts |
49 | 49 |
|
50 | 50 |
|
51 |
class TestIsProcessAlive(unittest.TestCase): |
|
52 |
"""Testing case for IsProcessAlive""" |
|
53 |
|
|
54 |
def testExists(self): |
|
55 |
mypid = os.getpid() |
|
56 |
self.assert_(utils.IsProcessAlive(mypid), "can't find myself running") |
|
57 |
|
|
58 |
def testNotExisting(self): |
|
59 |
pid_non_existing = os.fork() |
|
60 |
if pid_non_existing == 0: |
|
61 |
os._exit(0) |
|
62 |
elif pid_non_existing < 0: |
|
63 |
raise SystemError("can't fork") |
|
64 |
os.waitpid(pid_non_existing, 0) |
|
65 |
self.assertFalse(utils.IsProcessAlive(pid_non_existing), |
|
66 |
"nonexisting process detected") |
|
67 |
|
|
68 |
|
|
69 |
class TestGetProcStatusPath(unittest.TestCase): |
|
70 |
def test(self): |
|
71 |
self.assert_("/1234/" in utils._GetProcStatusPath(1234)) |
|
72 |
self.assertNotEqual(utils._GetProcStatusPath(1), |
|
73 |
utils._GetProcStatusPath(2)) |
|
74 |
|
|
75 |
|
|
76 |
class TestIsProcessHandlingSignal(unittest.TestCase): |
|
77 |
def setUp(self): |
|
78 |
self.tmpdir = tempfile.mkdtemp() |
|
79 |
|
|
80 |
def tearDown(self): |
|
81 |
shutil.rmtree(self.tmpdir) |
|
82 |
|
|
83 |
def testParseSigsetT(self): |
|
84 |
self.assertEqual(len(utils._ParseSigsetT("0")), 0) |
|
85 |
self.assertEqual(utils._ParseSigsetT("1"), set([1])) |
|
86 |
self.assertEqual(utils._ParseSigsetT("1000a"), set([2, 4, 17])) |
|
87 |
self.assertEqual(utils._ParseSigsetT("810002"), set([2, 17, 24, ])) |
|
88 |
self.assertEqual(utils._ParseSigsetT("0000000180000202"), |
|
89 |
set([2, 10, 32, 33])) |
|
90 |
self.assertEqual(utils._ParseSigsetT("0000000180000002"), |
|
91 |
set([2, 32, 33])) |
|
92 |
self.assertEqual(utils._ParseSigsetT("0000000188000002"), |
|
93 |
set([2, 28, 32, 33])) |
|
94 |
self.assertEqual(utils._ParseSigsetT("000000004b813efb"), |
|
95 |
set([1, 2, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 17, |
|
96 |
24, 25, 26, 28, 31])) |
|
97 |
self.assertEqual(utils._ParseSigsetT("ffffff"), set(range(1, 25))) |
|
98 |
|
|
99 |
def testGetProcStatusField(self): |
|
100 |
for field in ["SigCgt", "Name", "FDSize"]: |
|
101 |
for value in ["", "0", "cat", " 1234 KB"]: |
|
102 |
pstatus = "\n".join([ |
|
103 |
"VmPeak: 999 kB", |
|
104 |
"%s: %s" % (field, value), |
|
105 |
"TracerPid: 0", |
|
106 |
]) |
|
107 |
result = utils._GetProcStatusField(pstatus, field) |
|
108 |
self.assertEqual(result, value.strip()) |
|
109 |
|
|
110 |
def test(self): |
|
111 |
sp = utils.PathJoin(self.tmpdir, "status") |
|
112 |
|
|
113 |
utils.WriteFile(sp, data="\n".join([ |
|
114 |
"Name: bash", |
|
115 |
"State: S (sleeping)", |
|
116 |
"SleepAVG: 98%", |
|
117 |
"Pid: 22250", |
|
118 |
"PPid: 10858", |
|
119 |
"TracerPid: 0", |
|
120 |
"SigBlk: 0000000000010000", |
|
121 |
"SigIgn: 0000000000384004", |
|
122 |
"SigCgt: 000000004b813efb", |
|
123 |
"CapEff: 0000000000000000", |
|
124 |
])) |
|
125 |
|
|
126 |
self.assert_(utils.IsProcessHandlingSignal(1234, 10, status_path=sp)) |
|
127 |
|
|
128 |
def testNoSigCgt(self): |
|
129 |
sp = utils.PathJoin(self.tmpdir, "status") |
|
130 |
|
|
131 |
utils.WriteFile(sp, data="\n".join([ |
|
132 |
"Name: bash", |
|
133 |
])) |
|
134 |
|
|
135 |
self.assertRaises(RuntimeError, utils.IsProcessHandlingSignal, |
|
136 |
1234, 10, status_path=sp) |
|
137 |
|
|
138 |
def testNoSuchFile(self): |
|
139 |
sp = utils.PathJoin(self.tmpdir, "notexist") |
|
140 |
|
|
141 |
self.assertFalse(utils.IsProcessHandlingSignal(1234, 10, status_path=sp)) |
|
142 |
|
|
143 |
@staticmethod |
|
144 |
def _TestRealProcess(): |
|
145 |
signal.signal(signal.SIGUSR1, signal.SIG_DFL) |
|
146 |
if utils.IsProcessHandlingSignal(os.getpid(), signal.SIGUSR1): |
|
147 |
raise Exception("SIGUSR1 is handled when it should not be") |
|
148 |
|
|
149 |
signal.signal(signal.SIGUSR1, lambda signum, frame: None) |
|
150 |
if not utils.IsProcessHandlingSignal(os.getpid(), signal.SIGUSR1): |
|
151 |
raise Exception("SIGUSR1 is not handled when it should be") |
|
152 |
|
|
153 |
signal.signal(signal.SIGUSR1, signal.SIG_IGN) |
|
154 |
if utils.IsProcessHandlingSignal(os.getpid(), signal.SIGUSR1): |
|
155 |
raise Exception("SIGUSR1 is not handled when it should be") |
|
156 |
|
|
157 |
signal.signal(signal.SIGUSR1, signal.SIG_DFL) |
|
158 |
if utils.IsProcessHandlingSignal(os.getpid(), signal.SIGUSR1): |
|
159 |
raise Exception("SIGUSR1 is handled when it should not be") |
|
160 |
|
|
161 |
return True |
|
162 |
|
|
163 |
def testRealProcess(self): |
|
164 |
self.assert_(utils.RunInSeparateProcess(self._TestRealProcess)) |
|
165 |
|
|
166 |
|
|
167 |
class TestRunCmd(testutils.GanetiTestCase): |
|
168 |
"""Testing case for the RunCmd function""" |
|
169 |
|
|
170 |
def setUp(self): |
|
171 |
testutils.GanetiTestCase.setUp(self) |
|
172 |
self.magic = time.ctime() + " ganeti test" |
|
173 |
self.fname = self._CreateTempFile() |
|
174 |
self.fifo_tmpdir = tempfile.mkdtemp() |
|
175 |
self.fifo_file = os.path.join(self.fifo_tmpdir, "ganeti_test_fifo") |
|
176 |
os.mkfifo(self.fifo_file) |
|
177 |
|
|
178 |
def tearDown(self): |
|
179 |
shutil.rmtree(self.fifo_tmpdir) |
|
180 |
testutils.GanetiTestCase.tearDown(self) |
|
181 |
|
|
182 |
def testOk(self): |
|
183 |
"""Test successful exit code""" |
|
184 |
result = RunCmd("/bin/sh -c 'exit 0'") |
|
185 |
self.assertEqual(result.exit_code, 0) |
|
186 |
self.assertEqual(result.output, "") |
|
187 |
|
|
188 |
def testFail(self): |
|
189 |
"""Test fail exit code""" |
|
190 |
result = RunCmd("/bin/sh -c 'exit 1'") |
|
191 |
self.assertEqual(result.exit_code, 1) |
|
192 |
self.assertEqual(result.output, "") |
|
193 |
|
|
194 |
def testStdout(self): |
|
195 |
"""Test standard output""" |
|
196 |
cmd = 'echo -n "%s"' % self.magic |
|
197 |
result = RunCmd("/bin/sh -c '%s'" % cmd) |
|
198 |
self.assertEqual(result.stdout, self.magic) |
|
199 |
result = RunCmd("/bin/sh -c '%s'" % cmd, output=self.fname) |
|
200 |
self.assertEqual(result.output, "") |
|
201 |
self.assertFileContent(self.fname, self.magic) |
|
202 |
|
|
203 |
def testStderr(self): |
|
204 |
"""Test standard error""" |
|
205 |
cmd = 'echo -n "%s"' % self.magic |
|
206 |
result = RunCmd("/bin/sh -c '%s' 1>&2" % cmd) |
|
207 |
self.assertEqual(result.stderr, self.magic) |
|
208 |
result = RunCmd("/bin/sh -c '%s' 1>&2" % cmd, output=self.fname) |
|
209 |
self.assertEqual(result.output, "") |
|
210 |
self.assertFileContent(self.fname, self.magic) |
|
211 |
|
|
212 |
def testCombined(self): |
|
213 |
"""Test combined output""" |
|
214 |
cmd = 'echo -n "A%s"; echo -n "B%s" 1>&2' % (self.magic, self.magic) |
|
215 |
expected = "A" + self.magic + "B" + self.magic |
|
216 |
result = RunCmd("/bin/sh -c '%s'" % cmd) |
|
217 |
self.assertEqual(result.output, expected) |
|
218 |
result = RunCmd("/bin/sh -c '%s'" % cmd, output=self.fname) |
|
219 |
self.assertEqual(result.output, "") |
|
220 |
self.assertFileContent(self.fname, expected) |
|
221 |
|
|
222 |
def testSignal(self): |
|
223 |
"""Test signal""" |
|
224 |
result = RunCmd(["python", "-c", "import os; os.kill(os.getpid(), 15)"]) |
|
225 |
self.assertEqual(result.signal, 15) |
|
226 |
self.assertEqual(result.output, "") |
|
227 |
|
|
228 |
def testTimeoutClean(self): |
|
229 |
cmd = "trap 'exit 0' TERM; read < %s" % self.fifo_file |
|
230 |
result = RunCmd(["/bin/sh", "-c", cmd], timeout=0.2) |
|
231 |
self.assertEqual(result.exit_code, 0) |
|
232 |
|
|
233 |
def testTimeoutKill(self): |
|
234 |
cmd = ["/bin/sh", "-c", "trap '' TERM; read < %s" % self.fifo_file] |
|
235 |
timeout = 0.2 |
|
236 |
out, err, status, ta = utils._RunCmdPipe(cmd, {}, False, "/", False, |
|
237 |
timeout, _linger_timeout=0.2) |
|
238 |
self.assert_(status < 0) |
|
239 |
self.assertEqual(-status, signal.SIGKILL) |
|
240 |
|
|
241 |
def testTimeoutOutputAfterTerm(self): |
|
242 |
cmd = "trap 'echo sigtermed; exit 1' TERM; read < %s" % self.fifo_file |
|
243 |
result = RunCmd(["/bin/sh", "-c", cmd], timeout=0.2) |
|
244 |
self.assert_(result.failed) |
|
245 |
self.assertEqual(result.stdout, "sigtermed\n") |
|
246 |
|
|
247 |
def testListRun(self): |
|
248 |
"""Test list runs""" |
|
249 |
result = RunCmd(["true"]) |
|
250 |
self.assertEqual(result.signal, None) |
|
251 |
self.assertEqual(result.exit_code, 0) |
|
252 |
result = RunCmd(["/bin/sh", "-c", "exit 1"]) |
|
253 |
self.assertEqual(result.signal, None) |
|
254 |
self.assertEqual(result.exit_code, 1) |
|
255 |
result = RunCmd(["echo", "-n", self.magic]) |
|
256 |
self.assertEqual(result.signal, None) |
|
257 |
self.assertEqual(result.exit_code, 0) |
|
258 |
self.assertEqual(result.stdout, self.magic) |
|
259 |
|
|
260 |
def testFileEmptyOutput(self): |
|
261 |
"""Test file output""" |
|
262 |
result = RunCmd(["true"], output=self.fname) |
|
263 |
self.assertEqual(result.signal, None) |
|
264 |
self.assertEqual(result.exit_code, 0) |
|
265 |
self.assertFileContent(self.fname, "") |
|
266 |
|
|
267 |
def testLang(self): |
|
268 |
"""Test locale environment""" |
|
269 |
old_env = os.environ.copy() |
|
270 |
try: |
|
271 |
os.environ["LANG"] = "en_US.UTF-8" |
|
272 |
os.environ["LC_ALL"] = "en_US.UTF-8" |
|
273 |
result = RunCmd(["locale"]) |
|
274 |
for line in result.output.splitlines(): |
|
275 |
key, value = line.split("=", 1) |
|
276 |
# Ignore these variables, they're overridden by LC_ALL |
|
277 |
if key == "LANG" or key == "LANGUAGE": |
|
278 |
continue |
|
279 |
self.failIf(value and value != "C" and value != '"C"', |
|
280 |
"Variable %s is set to the invalid value '%s'" % (key, value)) |
|
281 |
finally: |
|
282 |
os.environ = old_env |
|
283 |
|
|
284 |
def testDefaultCwd(self): |
|
285 |
"""Test default working directory""" |
|
286 |
self.failUnlessEqual(RunCmd(["pwd"]).stdout.strip(), "/") |
|
287 |
|
|
288 |
def testCwd(self): |
|
289 |
"""Test default working directory""" |
|
290 |
self.failUnlessEqual(RunCmd(["pwd"], cwd="/").stdout.strip(), "/") |
|
291 |
self.failUnlessEqual(RunCmd(["pwd"], cwd="/tmp").stdout.strip(), "/tmp") |
|
292 |
cwd = os.getcwd() |
|
293 |
self.failUnlessEqual(RunCmd(["pwd"], cwd=cwd).stdout.strip(), cwd) |
|
294 |
|
|
295 |
def testResetEnv(self): |
|
296 |
"""Test environment reset functionality""" |
|
297 |
self.failUnlessEqual(RunCmd(["env"], reset_env=True).stdout.strip(), "") |
|
298 |
self.failUnlessEqual(RunCmd(["env"], reset_env=True, |
|
299 |
env={"FOO": "bar",}).stdout.strip(), "FOO=bar") |
|
300 |
|
|
301 |
def testNoFork(self): |
|
302 |
"""Test that nofork raise an error""" |
|
303 |
self.assertFalse(utils._no_fork) |
|
304 |
utils.DisableFork() |
|
305 |
try: |
|
306 |
self.assertTrue(utils._no_fork) |
|
307 |
self.assertRaises(errors.ProgrammerError, RunCmd, ["true"]) |
|
308 |
finally: |
|
309 |
utils._no_fork = False |
|
310 |
|
|
311 |
def testWrongParams(self): |
|
312 |
"""Test wrong parameters""" |
|
313 |
self.assertRaises(errors.ProgrammerError, RunCmd, ["true"], |
|
314 |
output="/dev/null", interactive=True) |
|
315 |
|
|
316 |
|
|
317 |
class TestRunParts(testutils.GanetiTestCase): |
|
318 |
"""Testing case for the RunParts function""" |
|
319 |
|
|
320 |
def setUp(self): |
|
321 |
self.rundir = tempfile.mkdtemp(prefix="ganeti-test", suffix=".tmp") |
|
322 |
|
|
323 |
def tearDown(self): |
|
324 |
shutil.rmtree(self.rundir) |
|
325 |
|
|
326 |
def testEmpty(self): |
|
327 |
"""Test on an empty dir""" |
|
328 |
self.failUnlessEqual(RunParts(self.rundir, reset_env=True), []) |
|
329 |
|
|
330 |
def testSkipWrongName(self): |
|
331 |
"""Test that wrong files are skipped""" |
|
332 |
fname = os.path.join(self.rundir, "00test.dot") |
|
333 |
utils.WriteFile(fname, data="") |
|
334 |
os.chmod(fname, stat.S_IREAD | stat.S_IEXEC) |
|
335 |
relname = os.path.basename(fname) |
|
336 |
self.failUnlessEqual(RunParts(self.rundir, reset_env=True), |
|
337 |
[(relname, constants.RUNPARTS_SKIP, None)]) |
|
338 |
|
|
339 |
def testSkipNonExec(self): |
|
340 |
"""Test that non executable files are skipped""" |
|
341 |
fname = os.path.join(self.rundir, "00test") |
|
342 |
utils.WriteFile(fname, data="") |
|
343 |
relname = os.path.basename(fname) |
|
344 |
self.failUnlessEqual(RunParts(self.rundir, reset_env=True), |
|
345 |
[(relname, constants.RUNPARTS_SKIP, None)]) |
|
346 |
|
|
347 |
def testError(self): |
|
348 |
"""Test error on a broken executable""" |
|
349 |
fname = os.path.join(self.rundir, "00test") |
|
350 |
utils.WriteFile(fname, data="") |
|
351 |
os.chmod(fname, stat.S_IREAD | stat.S_IEXEC) |
|
352 |
(relname, status, error) = RunParts(self.rundir, reset_env=True)[0] |
|
353 |
self.failUnlessEqual(relname, os.path.basename(fname)) |
|
354 |
self.failUnlessEqual(status, constants.RUNPARTS_ERR) |
|
355 |
self.failUnless(error) |
|
356 |
|
|
357 |
def testSorted(self): |
|
358 |
"""Test executions are sorted""" |
|
359 |
files = [] |
|
360 |
files.append(os.path.join(self.rundir, "64test")) |
|
361 |
files.append(os.path.join(self.rundir, "00test")) |
|
362 |
files.append(os.path.join(self.rundir, "42test")) |
|
363 |
|
|
364 |
for fname in files: |
|
365 |
utils.WriteFile(fname, data="") |
|
366 |
|
|
367 |
results = RunParts(self.rundir, reset_env=True) |
|
368 |
|
|
369 |
for fname in sorted(files): |
|
370 |
self.failUnlessEqual(os.path.basename(fname), results.pop(0)[0]) |
|
371 |
|
|
372 |
def testOk(self): |
|
373 |
"""Test correct execution""" |
|
374 |
fname = os.path.join(self.rundir, "00test") |
|
375 |
utils.WriteFile(fname, data="#!/bin/sh\n\necho -n ciao") |
|
376 |
os.chmod(fname, stat.S_IREAD | stat.S_IEXEC) |
|
377 |
(relname, status, runresult) = RunParts(self.rundir, reset_env=True)[0] |
|
378 |
self.failUnlessEqual(relname, os.path.basename(fname)) |
|
379 |
self.failUnlessEqual(status, constants.RUNPARTS_RUN) |
|
380 |
self.failUnlessEqual(runresult.stdout, "ciao") |
|
381 |
|
|
382 |
def testRunFail(self): |
|
383 |
"""Test correct execution, with run failure""" |
|
384 |
fname = os.path.join(self.rundir, "00test") |
|
385 |
utils.WriteFile(fname, data="#!/bin/sh\n\nexit 1") |
|
386 |
os.chmod(fname, stat.S_IREAD | stat.S_IEXEC) |
|
387 |
(relname, status, runresult) = RunParts(self.rundir, reset_env=True)[0] |
|
388 |
self.failUnlessEqual(relname, os.path.basename(fname)) |
|
389 |
self.failUnlessEqual(status, constants.RUNPARTS_RUN) |
|
390 |
self.failUnlessEqual(runresult.exit_code, 1) |
|
391 |
self.failUnless(runresult.failed) |
|
392 |
|
|
393 |
def testRunMix(self): |
|
394 |
files = [] |
|
395 |
files.append(os.path.join(self.rundir, "00test")) |
|
396 |
files.append(os.path.join(self.rundir, "42test")) |
|
397 |
files.append(os.path.join(self.rundir, "64test")) |
|
398 |
files.append(os.path.join(self.rundir, "99test")) |
|
399 |
|
|
400 |
files.sort() |
|
401 |
|
|
402 |
# 1st has errors in execution |
|
403 |
utils.WriteFile(files[0], data="#!/bin/sh\n\nexit 1") |
|
404 |
os.chmod(files[0], stat.S_IREAD | stat.S_IEXEC) |
|
405 |
|
|
406 |
# 2nd is skipped |
|
407 |
utils.WriteFile(files[1], data="") |
|
408 |
|
|
409 |
# 3rd cannot execute properly |
|
410 |
utils.WriteFile(files[2], data="") |
|
411 |
os.chmod(files[2], stat.S_IREAD | stat.S_IEXEC) |
|
412 |
|
|
413 |
# 4th execs |
|
414 |
utils.WriteFile(files[3], data="#!/bin/sh\n\necho -n ciao") |
|
415 |
os.chmod(files[3], stat.S_IREAD | stat.S_IEXEC) |
|
416 |
|
|
417 |
results = RunParts(self.rundir, reset_env=True) |
|
418 |
|
|
419 |
(relname, status, runresult) = results[0] |
|
420 |
self.failUnlessEqual(relname, os.path.basename(files[0])) |
|
421 |
self.failUnlessEqual(status, constants.RUNPARTS_RUN) |
|
422 |
self.failUnlessEqual(runresult.exit_code, 1) |
|
423 |
self.failUnless(runresult.failed) |
|
424 |
|
|
425 |
(relname, status, runresult) = results[1] |
|
426 |
self.failUnlessEqual(relname, os.path.basename(files[1])) |
|
427 |
self.failUnlessEqual(status, constants.RUNPARTS_SKIP) |
|
428 |
self.failUnlessEqual(runresult, None) |
|
429 |
|
|
430 |
(relname, status, runresult) = results[2] |
|
431 |
self.failUnlessEqual(relname, os.path.basename(files[2])) |
|
432 |
self.failUnlessEqual(status, constants.RUNPARTS_ERR) |
|
433 |
self.failUnless(runresult) |
|
434 |
|
|
435 |
(relname, status, runresult) = results[3] |
|
436 |
self.failUnlessEqual(relname, os.path.basename(files[3])) |
|
437 |
self.failUnlessEqual(status, constants.RUNPARTS_RUN) |
|
438 |
self.failUnlessEqual(runresult.output, "ciao") |
|
439 |
self.failUnlessEqual(runresult.exit_code, 0) |
|
440 |
self.failUnless(not runresult.failed) |
|
441 |
|
|
442 |
def testMissingDirectory(self): |
|
443 |
nosuchdir = utils.PathJoin(self.rundir, "no/such/directory") |
|
444 |
self.assertEqual(RunParts(nosuchdir), []) |
|
445 |
|
|
446 |
|
|
447 |
class TestStartDaemon(testutils.GanetiTestCase): |
|
448 |
def setUp(self): |
|
449 |
self.tmpdir = tempfile.mkdtemp(prefix="ganeti-test") |
|
450 |
self.tmpfile = os.path.join(self.tmpdir, "test") |
|
451 |
|
|
452 |
def tearDown(self): |
|
453 |
shutil.rmtree(self.tmpdir) |
|
454 |
|
|
455 |
def testShell(self): |
|
456 |
utils.StartDaemon("echo Hello World > %s" % self.tmpfile) |
|
457 |
self._wait(self.tmpfile, 60.0, "Hello World") |
|
458 |
|
|
459 |
def testShellOutput(self): |
|
460 |
utils.StartDaemon("echo Hello World", output=self.tmpfile) |
|
461 |
self._wait(self.tmpfile, 60.0, "Hello World") |
|
462 |
|
|
463 |
def testNoShellNoOutput(self): |
|
464 |
utils.StartDaemon(["pwd"]) |
|
465 |
|
|
466 |
def testNoShellNoOutputTouch(self): |
|
467 |
testfile = os.path.join(self.tmpdir, "check") |
|
468 |
self.failIf(os.path.exists(testfile)) |
|
469 |
utils.StartDaemon(["touch", testfile]) |
|
470 |
self._wait(testfile, 60.0, "") |
|
471 |
|
|
472 |
def testNoShellOutput(self): |
|
473 |
utils.StartDaemon(["pwd"], output=self.tmpfile) |
|
474 |
self._wait(self.tmpfile, 60.0, "/") |
|
475 |
|
|
476 |
def testNoShellOutputCwd(self): |
|
477 |
utils.StartDaemon(["pwd"], output=self.tmpfile, cwd=os.getcwd()) |
|
478 |
self._wait(self.tmpfile, 60.0, os.getcwd()) |
|
479 |
|
|
480 |
def testShellEnv(self): |
|
481 |
utils.StartDaemon("echo \"$GNT_TEST_VAR\"", output=self.tmpfile, |
|
482 |
env={ "GNT_TEST_VAR": "Hello World", }) |
|
483 |
self._wait(self.tmpfile, 60.0, "Hello World") |
|
484 |
|
|
485 |
def testNoShellEnv(self): |
|
486 |
utils.StartDaemon(["printenv", "GNT_TEST_VAR"], output=self.tmpfile, |
|
487 |
env={ "GNT_TEST_VAR": "Hello World", }) |
|
488 |
self._wait(self.tmpfile, 60.0, "Hello World") |
|
489 |
|
|
490 |
def testOutputFd(self): |
|
491 |
fd = os.open(self.tmpfile, os.O_WRONLY | os.O_CREAT) |
|
492 |
try: |
|
493 |
utils.StartDaemon(["pwd"], output_fd=fd, cwd=os.getcwd()) |
|
494 |
finally: |
|
495 |
os.close(fd) |
|
496 |
self._wait(self.tmpfile, 60.0, os.getcwd()) |
|
497 |
|
|
498 |
def testPid(self): |
|
499 |
pid = utils.StartDaemon("echo $$ > %s" % self.tmpfile) |
|
500 |
self._wait(self.tmpfile, 60.0, str(pid)) |
|
501 |
|
|
502 |
def testPidFile(self): |
|
503 |
pidfile = os.path.join(self.tmpdir, "pid") |
|
504 |
checkfile = os.path.join(self.tmpdir, "abort") |
|
505 |
|
|
506 |
pid = utils.StartDaemon("while sleep 5; do :; done", pidfile=pidfile, |
|
507 |
output=self.tmpfile) |
|
508 |
try: |
|
509 |
fd = os.open(pidfile, os.O_RDONLY) |
|
510 |
try: |
|
511 |
# Check file is locked |
|
512 |
self.assertRaises(errors.LockError, utils.LockFile, fd) |
|
513 |
|
|
514 |
pidtext = os.read(fd, 100) |
|
515 |
finally: |
|
516 |
os.close(fd) |
|
517 |
|
|
518 |
self.assertEqual(int(pidtext.strip()), pid) |
|
519 |
|
|
520 |
self.assert_(utils.IsProcessAlive(pid)) |
|
521 |
finally: |
|
522 |
# No matter what happens, kill daemon |
|
523 |
utils.KillProcess(pid, timeout=5.0, waitpid=False) |
|
524 |
self.failIf(utils.IsProcessAlive(pid)) |
|
525 |
|
|
526 |
self.assertEqual(utils.ReadFile(self.tmpfile), "") |
|
527 |
|
|
528 |
def _wait(self, path, timeout, expected): |
|
529 |
# Due to the asynchronous nature of daemon processes, polling is necessary. |
|
530 |
# A timeout makes sure the test doesn't hang forever. |
|
531 |
def _CheckFile(): |
|
532 |
if not (os.path.isfile(path) and |
|
533 |
utils.ReadFile(path).strip() == expected): |
|
534 |
raise utils.RetryAgain() |
|
535 |
|
|
536 |
try: |
|
537 |
utils.Retry(_CheckFile, (0.01, 1.5, 1.0), timeout) |
|
538 |
except utils.RetryTimeout: |
|
539 |
self.fail("Apparently the daemon didn't run in %s seconds and/or" |
|
540 |
" didn't write the correct output" % timeout) |
|
541 |
|
|
542 |
def testError(self): |
|
543 |
self.assertRaises(errors.OpExecError, utils.StartDaemon, |
|
544 |
["./does-NOT-EXIST/here/0123456789"]) |
|
545 |
self.assertRaises(errors.OpExecError, utils.StartDaemon, |
|
546 |
["./does-NOT-EXIST/here/0123456789"], |
|
547 |
output=os.path.join(self.tmpdir, "DIR/NOT/EXIST")) |
|
548 |
self.assertRaises(errors.OpExecError, utils.StartDaemon, |
|
549 |
["./does-NOT-EXIST/here/0123456789"], |
|
550 |
cwd=os.path.join(self.tmpdir, "DIR/NOT/EXIST")) |
|
551 |
self.assertRaises(errors.OpExecError, utils.StartDaemon, |
|
552 |
["./does-NOT-EXIST/here/0123456789"], |
|
553 |
output=os.path.join(self.tmpdir, "DIR/NOT/EXIST")) |
|
554 |
|
|
555 |
fd = os.open(self.tmpfile, os.O_WRONLY | os.O_CREAT) |
|
556 |
try: |
|
557 |
self.assertRaises(errors.ProgrammerError, utils.StartDaemon, |
|
558 |
["./does-NOT-EXIST/here/0123456789"], |
|
559 |
output=self.tmpfile, output_fd=fd) |
|
560 |
finally: |
|
561 |
os.close(fd) |
|
562 |
|
|
563 |
|
|
564 | 51 |
class TestParseCpuMask(unittest.TestCase): |
565 | 52 |
"""Test case for the ParseCpuMask function.""" |
566 | 53 |
|
... | ... | |
714 | 201 |
{"b": "hello"}, {"b": "no-such-type"}) |
715 | 202 |
|
716 | 203 |
|
717 |
class RunInSeparateProcess(unittest.TestCase): |
|
718 |
def test(self): |
|
719 |
for exp in [True, False]: |
|
720 |
def _child(): |
|
721 |
return exp |
|
722 |
|
|
723 |
self.assertEqual(exp, utils.RunInSeparateProcess(_child)) |
|
724 |
|
|
725 |
def testArgs(self): |
|
726 |
for arg in [0, 1, 999, "Hello World", (1, 2, 3)]: |
|
727 |
def _child(carg1, carg2): |
|
728 |
return carg1 == "Foo" and carg2 == arg |
|
729 |
|
|
730 |
self.assert_(utils.RunInSeparateProcess(_child, "Foo", arg)) |
|
731 |
|
|
732 |
def testPid(self): |
|
733 |
parent_pid = os.getpid() |
|
734 |
|
|
735 |
def _check(): |
|
736 |
return os.getpid() == parent_pid |
|
737 |
|
|
738 |
self.failIf(utils.RunInSeparateProcess(_check)) |
|
739 |
|
|
740 |
def testSignal(self): |
|
741 |
def _kill(): |
|
742 |
os.kill(os.getpid(), signal.SIGTERM) |
|
743 |
|
|
744 |
self.assertRaises(errors.GenericError, |
|
745 |
utils.RunInSeparateProcess, _kill) |
|
746 |
|
|
747 |
def testException(self): |
|
748 |
def _exc(): |
|
749 |
raise errors.GenericError("This is a test") |
|
750 |
|
|
751 |
self.assertRaises(errors.GenericError, |
|
752 |
utils.RunInSeparateProcess, _exc) |
|
753 |
|
|
754 |
|
|
755 | 204 |
class TestValidateServiceName(unittest.TestCase): |
756 | 205 |
def testValid(self): |
757 | 206 |
testnames = [ |
Also available in: Unified diff