import socket
import shutil
import re
+import select
import ganeti
import testutils
RemoveFile, CheckDict, MatchNameComponent, FormatUnit, \
ParseUnit, AddAuthorizedKey, RemoveAuthorizedKey, \
ShellQuote, ShellQuoteArgs, TcpPing, ListVisibleFiles, \
- SetEtcHostsEntry, RemoveEtcHostsEntry, FirstFree
+ SetEtcHostsEntry, RemoveEtcHostsEntry, FirstFree, OwnIpAddress
from ganeti.errors import LockError, UnitParseError, GenericError, \
ProgrammerError
-def _ChildHandler(signal, stack):
- global _ChildFlag
- _ChildFlag = True
-
class TestIsProcessAlive(unittest.TestCase):
"""Testing case for IsProcessAlive"""
- def setUp(self):
- global _ChildFlag
- # create a (most probably) non-existing process-id
- self.pid_non_existing = os.fork()
- if self.pid_non_existing == 0:
- os._exit(0)
- elif self.pid_non_existing > 0:
- os.waitpid(self.pid_non_existing, 0)
- else:
- raise SystemError("can't fork")
- _ChildFlag = False
- # Use _ChildHandler for SIGCHLD
- self.chldOrig = signal.signal(signal.SIGCHLD, _ChildHandler)
- # create a zombie
- self.pid_zombie = os.fork()
- if self.pid_zombie == 0:
- os._exit(0)
- elif self.pid_zombie < 0:
- raise SystemError("can't fork")
-
- def tearDown(self):
- signal.signal(signal.SIGCHLD, self.chldOrig)
-
def testExists(self):
mypid = os.getpid()
self.assert_(IsProcessAlive(mypid),
"can't find myself running")
- def testZombie(self):
- global _ChildFlag
- timeout = 10
-
- while not _ChildFlag:
- if timeout >= 0:
- time.sleep(0.2)
- timeout -= 0.2
- else:
- self.fail("timed out waiting for child's signal")
- break # not executed...
-
- self.assert_(not IsProcessAlive(self.pid_zombie),
- "zombie not detected as zombie")
-
def testNotExisting(self):
- self.assert_(not IsProcessAlive(self.pid_non_existing),
- "noexisting process detected")
+ pid_non_existing = os.fork()
+ if pid_non_existing == 0:
+ os._exit(0)
+ elif pid_non_existing < 0:
+ raise SystemError("can't fork")
+ os.waitpid(pid_non_existing, 0)
+ self.assert_(not IsProcessAlive(pid_non_existing),
+ "nonexisting process detected")
class TestPidFileFunctions(unittest.TestCase):
read_pid = utils.ReadPidFile(pid_file)
self.failUnlessEqual(read_pid, new_pid)
self.failUnless(utils.IsProcessAlive(new_pid))
- utils.KillProcess(new_pid)
+ utils.KillProcess(new_pid, waitpid=True)
self.failIf(utils.IsProcessAlive(new_pid))
utils.RemovePidFile('child')
self.failUnlessRaises(ProgrammerError, utils.KillProcess, 0)
os.rmdir(self.dir)
-class TestRunCmd(unittest.TestCase):
+class TestRunCmd(testutils.GanetiTestCase):
"""Testing case for the RunCmd function"""
def setUp(self):
self.magic = time.ctime() + " ganeti test"
+ fh, self.fname = tempfile.mkstemp()
+ os.close(fh)
+
+ def tearDown(self):
+ if self.fname:
+ utils.RemoveFile(self.fname)
def testOk(self):
"""Test successful exit code"""
result = RunCmd("/bin/sh -c 'exit 0'")
self.assertEqual(result.exit_code, 0)
+ self.assertEqual(result.output, "")
def testFail(self):
"""Test fail exit code"""
result = RunCmd("/bin/sh -c 'exit 1'")
self.assertEqual(result.exit_code, 1)
-
+ self.assertEqual(result.output, "")
def testStdout(self):
"""Test standard output"""
cmd = 'echo -n "%s"' % self.magic
result = RunCmd("/bin/sh -c '%s'" % cmd)
self.assertEqual(result.stdout, self.magic)
-
+ result = RunCmd("/bin/sh -c '%s'" % cmd, output=self.fname)
+ self.assertEqual(result.output, "")
+ self.assertFileContent(self.fname, self.magic)
def testStderr(self):
"""Test standard error"""
cmd = 'echo -n "%s"' % self.magic
result = RunCmd("/bin/sh -c '%s' 1>&2" % cmd)
self.assertEqual(result.stderr, self.magic)
-
+ result = RunCmd("/bin/sh -c '%s' 1>&2" % cmd, output=self.fname)
+ self.assertEqual(result.output, "")
+ self.assertFileContent(self.fname, self.magic)
def testCombined(self):
"""Test combined output"""
cmd = 'echo -n "A%s"; echo -n "B%s" 1>&2' % (self.magic, self.magic)
+ expected = "A" + self.magic + "B" + self.magic
result = RunCmd("/bin/sh -c '%s'" % cmd)
- self.assertEqual(result.output, "A" + self.magic + "B" + self.magic)
+ self.assertEqual(result.output, expected)
+ result = RunCmd("/bin/sh -c '%s'" % cmd, output=self.fname)
+ self.assertEqual(result.output, "")
+ self.assertFileContent(self.fname, expected)
def testSignal(self):
"""Test signal"""
result = RunCmd(["python", "-c", "import os; os.kill(os.getpid(), 15)"])
self.assertEqual(result.signal, 15)
+ self.assertEqual(result.output, "")
def testListRun(self):
"""Test list runs"""
self.assertEqual(result.exit_code, 0)
self.assertEqual(result.stdout, self.magic)
+ def testFileEmptyOutput(self):
+ """Test file output"""
+ result = RunCmd(["true"], output=self.fname)
+ self.assertEqual(result.signal, None)
+ self.assertEqual(result.exit_code, 0)
+ self.assertFileContent(self.fname, "")
+
def testLang(self):
"""Test locale environment"""
old_env = os.environ.copy()
finally:
os.environ = old_env
+ def testDefaultCwd(self):
+ """Test default working directory"""
+ self.failUnlessEqual(RunCmd(["pwd"]).stdout.strip(), "/")
+
+ def testCwd(self):
+ """Test default working directory"""
+ self.failUnlessEqual(RunCmd(["pwd"], cwd="/").stdout.strip(), "/")
+ self.failUnlessEqual(RunCmd(["pwd"], cwd="/tmp").stdout.strip(), "/tmp")
+ cwd = os.getcwd()
+ self.failUnlessEqual(RunCmd(["pwd"], cwd=cwd).stdout.strip(), cwd)
+
class TestRemoveFile(unittest.TestCase):
"""Test case for the RemoveFile function"""
self.fail("File '%s' not removed" % symlink)
+class TestRename(unittest.TestCase):
+ """Test case for RenameFile"""
+
+ def setUp(self):
+ """Create a temporary directory"""
+ self.tmpdir = tempfile.mkdtemp()
+ self.tmpfile = os.path.join(self.tmpdir, "test1")
+
+ # Touch the file
+ open(self.tmpfile, "w").close()
+
+ def tearDown(self):
+ """Remove temporary directory"""
+ shutil.rmtree(self.tmpdir)
+
+ def testSimpleRename1(self):
+ """Simple rename 1"""
+ utils.RenameFile(self.tmpfile, os.path.join(self.tmpdir, "xyz"))
+
+ def testSimpleRename2(self):
+ """Simple rename 2"""
+ utils.RenameFile(self.tmpfile, os.path.join(self.tmpdir, "xyz"),
+ mkdir=True)
+
+ def testRenameMkdir(self):
+ """Rename with mkdir"""
+ utils.RenameFile(self.tmpfile, os.path.join(self.tmpdir, "test/xyz"),
+ mkdir=True)
+
+
class TestCheckdict(unittest.TestCase):
"""Test case for the CheckDict function"""
"""Test case for the FormatUnit function"""
def testMiB(self):
- self.assertEqual(FormatUnit(1), '1M')
- self.assertEqual(FormatUnit(100), '100M')
- self.assertEqual(FormatUnit(1023), '1023M')
+ self.assertEqual(FormatUnit(1, 'h'), '1M')
+ self.assertEqual(FormatUnit(100, 'h'), '100M')
+ self.assertEqual(FormatUnit(1023, 'h'), '1023M')
+
+ self.assertEqual(FormatUnit(1, 'm'), '1')
+ self.assertEqual(FormatUnit(100, 'm'), '100')
+ self.assertEqual(FormatUnit(1023, 'm'), '1023')
+
+ self.assertEqual(FormatUnit(1024, 'm'), '1024')
+ self.assertEqual(FormatUnit(1536, 'm'), '1536')
+ self.assertEqual(FormatUnit(17133, 'm'), '17133')
+ self.assertEqual(FormatUnit(1024 * 1024 - 1, 'm'), '1048575')
def testGiB(self):
- self.assertEqual(FormatUnit(1024), '1.0G')
- self.assertEqual(FormatUnit(1536), '1.5G')
- self.assertEqual(FormatUnit(17133), '16.7G')
- self.assertEqual(FormatUnit(1024 * 1024 - 1), '1024.0G')
+ self.assertEqual(FormatUnit(1024, 'h'), '1.0G')
+ self.assertEqual(FormatUnit(1536, 'h'), '1.5G')
+ self.assertEqual(FormatUnit(17133, 'h'), '16.7G')
+ self.assertEqual(FormatUnit(1024 * 1024 - 1, 'h'), '1024.0G')
+
+ self.assertEqual(FormatUnit(1024, 'g'), '1.0')
+ self.assertEqual(FormatUnit(1536, 'g'), '1.5')
+ self.assertEqual(FormatUnit(17133, 'g'), '16.7')
+ self.assertEqual(FormatUnit(1024 * 1024 - 1, 'g'), '1024.0')
+
+ self.assertEqual(FormatUnit(1024 * 1024, 'g'), '1024.0')
+ self.assertEqual(FormatUnit(5120 * 1024, 'g'), '5120.0')
+ self.assertEqual(FormatUnit(29829 * 1024, 'g'), '29829.0')
def testTiB(self):
- self.assertEqual(FormatUnit(1024 * 1024), '1.0T')
- self.assertEqual(FormatUnit(5120 * 1024), '5.0T')
- self.assertEqual(FormatUnit(29829 * 1024), '29.1T')
+ self.assertEqual(FormatUnit(1024 * 1024, 'h'), '1.0T')
+ self.assertEqual(FormatUnit(5120 * 1024, 'h'), '5.0T')
+ self.assertEqual(FormatUnit(29829 * 1024, 'h'), '29.1T')
+ self.assertEqual(FormatUnit(1024 * 1024, 't'), '1.0')
+ self.assertEqual(FormatUnit(5120 * 1024, 't'), '5.0')
+ self.assertEqual(FormatUnit(29829 * 1024, 't'), '29.1')
class TestParseUnit(unittest.TestCase):
"""Test case for the ParseUnit function"""
"failed to ping alive host on deaf port (no source addr)")
+class TestOwnIpAddress(unittest.TestCase):
+ """Testcase for OwnIpAddress"""
+
+ def testOwnLoopback(self):
+ """check having the loopback ip"""
+ self.failUnless(OwnIpAddress(constants.LOCALHOST_IP_ADDRESS),
+ "Should own the loopback address")
+
+ def testNowOwnAddress(self):
+ """check that I don't own an address"""
+
+ # network 192.0.2.0/24 is reserved for test/documentation as per
+ # rfc 3330, so we *should* not have an address of this range... if
+ # this fails, we should extend the test to multiple addresses
+ DST_IP = "192.0.2.1"
+ self.failIf(OwnIpAddress(DST_IP), "Should not own IP address %s" % DST_IP)
+
+
class TestListVisibleFiles(unittest.TestCase):
"""Test case for ListVisibleFiles"""
def runTest(self):
self.assertEqual(utils.SplitTime(1), (1, 0))
- self.assertEqual(utils.SplitTime(1.5), (1, 500))
- self.assertEqual(utils.SplitTime(1218448917.4809151), (1218448917, 481))
- self.assertEqual(utils.SplitTime(123.48012), (123, 480))
- self.assertEqual(utils.SplitTime(123.9995), (124, 0))
- self.assertEqual(utils.SplitTime(123.999999999), (124, 0))
+ self.assertEqual(utils.SplitTime(1.5), (1, 500000))
+ self.assertEqual(utils.SplitTime(1218448917.4809151), (1218448917, 480915))
+ self.assertEqual(utils.SplitTime(123.48012), (123, 480120))
+ self.assertEqual(utils.SplitTime(123.9996), (123, 999600))
+ self.assertEqual(utils.SplitTime(123.9995), (123, 999500))
+ self.assertEqual(utils.SplitTime(123.9994), (123, 999400))
+ self.assertEqual(utils.SplitTime(123.999999999), (123, 999999))
+
+ self.assertRaises(AssertionError, utils.SplitTime, -1)
self.assertEqual(utils.MergeTime((1, 0)), 1.0)
- self.assertEqual(utils.MergeTime((1, 500)), 1.5)
- self.assertEqual(utils.MergeTime((1218448917, 500)), 1218448917.5)
+ self.assertEqual(utils.MergeTime((1, 500000)), 1.5)
+ self.assertEqual(utils.MergeTime((1218448917, 500000)), 1218448917.5)
- self.assertEqual(round(utils.MergeTime((1218448917, 481)), 3), 1218448917.481)
- self.assertEqual(round(utils.MergeTime((1, 801)), 3), 1.801)
+ self.assertEqual(round(utils.MergeTime((1218448917, 481000)), 3), 1218448917.481)
+ self.assertEqual(round(utils.MergeTime((1, 801000)), 3), 1.801)
self.assertRaises(AssertionError, utils.MergeTime, (0, -1))
- self.assertRaises(AssertionError, utils.MergeTime, (0, 1000))
- self.assertRaises(AssertionError, utils.MergeTime, (0, 9999))
+ self.assertRaises(AssertionError, utils.MergeTime, (0, 1000000))
+ self.assertRaises(AssertionError, utils.MergeTime, (0, 9999999))
self.assertRaises(AssertionError, utils.MergeTime, (-1, 0))
self.assertRaises(AssertionError, utils.MergeTime, (-9999, 0))
+class FieldSetTestCase(unittest.TestCase):
+ """Test case for FieldSets"""
+
+ def testSimpleMatch(self):
+ f = utils.FieldSet("a", "b", "c", "def")
+ self.failUnless(f.Matches("a"))
+ self.failIf(f.Matches("d"), "Substring matched")
+ self.failIf(f.Matches("defghi"), "Prefix string matched")
+ self.failIf(f.NonMatching(["b", "c"]))
+ self.failIf(f.NonMatching(["a", "b", "c", "def"]))
+ self.failUnless(f.NonMatching(["a", "d"]))
+
+ def testRegexMatch(self):
+ f = utils.FieldSet("a", "b([0-9]+)", "c")
+ self.failUnless(f.Matches("b1"))
+ self.failUnless(f.Matches("b99"))
+ self.failIf(f.Matches("b/1"))
+ self.failIf(f.NonMatching(["b12", "c"]))
+ self.failUnless(f.NonMatching(["a", "1"]))
+
+
if __name__ == '__main__':
unittest.main()