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