Migrate test/ganeti.*.py from constants to pathutils
[ganeti-local] / test / ganeti.mcpu_unittest.py
1 #!/usr/bin/python
2 #
3
4 # Copyright (C) 2009, 2011 Google Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 # 02110-1301, USA.
20
21
22 """Script for unittesting the mcpu module"""
23
24
25 import unittest
26 import itertools
27
28 from ganeti import mcpu
29 from ganeti import opcodes
30 from ganeti import cmdlib
31 from ganeti import constants
32 from ganeti.constants import \
33     LOCK_ATTEMPTS_TIMEOUT, \
34     LOCK_ATTEMPTS_MAXWAIT, \
35     LOCK_ATTEMPTS_MINWAIT
36
37 import testutils
38
39
40 REQ_BGL_WHITELIST = frozenset([
41   opcodes.OpClusterActivateMasterIp,
42   opcodes.OpClusterDeactivateMasterIp,
43   opcodes.OpClusterDestroy,
44   opcodes.OpClusterPostInit,
45   opcodes.OpClusterRename,
46   opcodes.OpInstanceRename,
47   opcodes.OpNodeAdd,
48   opcodes.OpNodeRemove,
49   opcodes.OpTestAllocator,
50   ])
51
52
53 class TestLockAttemptTimeoutStrategy(unittest.TestCase):
54   def testConstants(self):
55     tpa = mcpu.LockAttemptTimeoutStrategy._TIMEOUT_PER_ATTEMPT
56     self.assert_(len(tpa) > LOCK_ATTEMPTS_TIMEOUT / LOCK_ATTEMPTS_MAXWAIT)
57     self.assert_(sum(tpa) >= LOCK_ATTEMPTS_TIMEOUT)
58
59     self.assertTrue(LOCK_ATTEMPTS_TIMEOUT >= 1800,
60                     msg="Waiting less than half an hour per priority")
61     self.assertTrue(LOCK_ATTEMPTS_TIMEOUT <= 3600,
62                     msg="Waiting more than an hour per priority")
63
64   def testSimple(self):
65     strat = mcpu.LockAttemptTimeoutStrategy(_random_fn=lambda: 0.5,
66                                             _time_fn=lambda: 0.0)
67
68     prev = None
69     for i in range(len(strat._TIMEOUT_PER_ATTEMPT)):
70       timeout = strat.NextAttempt()
71       self.assert_(timeout is not None)
72
73       self.assert_(timeout <= LOCK_ATTEMPTS_MAXWAIT)
74       self.assert_(timeout >= LOCK_ATTEMPTS_MINWAIT)
75       self.assert_(prev is None or timeout >= prev)
76
77       prev = timeout
78
79     for _ in range(10):
80       self.assert_(strat.NextAttempt() is None)
81
82
83 class TestDispatchTable(unittest.TestCase):
84   def test(self):
85     for opcls in opcodes.OP_MAPPING.values():
86       if not opcls.WITH_LU:
87         continue
88       self.assertTrue(opcls in mcpu.Processor.DISPATCH_TABLE,
89                       msg="%s missing handler class" % opcls)
90
91       # Check against BGL whitelist
92       lucls = mcpu.Processor.DISPATCH_TABLE[opcls]
93       if lucls.REQ_BGL:
94         self.assertTrue(opcls in REQ_BGL_WHITELIST,
95                         msg=("%s not whitelisted for BGL" % opcls.OP_ID))
96       else:
97         self.assertFalse(opcls in REQ_BGL_WHITELIST,
98                          msg=("%s whitelisted for BGL, but doesn't use it" %
99                               opcls.OP_ID))
100
101
102 class TestProcessResult(unittest.TestCase):
103   def setUp(self):
104     self._submitted = []
105     self._count = itertools.count(200)
106
107   def _Submit(self, jobs):
108     job_ids = [self._count.next() for _ in jobs]
109     self._submitted.extend(zip(job_ids, jobs))
110     return job_ids
111
112   def testNoJobs(self):
113     for i in [object(), [], False, True, None, 1, 929, {}]:
114       self.assertEqual(mcpu._ProcessResult(NotImplemented, NotImplemented, i),
115                        i)
116
117   def testDefaults(self):
118     src = opcodes.OpTestDummy()
119
120     res = mcpu._ProcessResult(self._Submit, src, cmdlib.ResultWithJobs([[
121       opcodes.OpTestDelay(),
122       opcodes.OpTestDelay(),
123       ], [
124       opcodes.OpTestDelay(),
125       ]]))
126
127     self.assertEqual(res, {
128       constants.JOB_IDS_KEY: [200, 201],
129       })
130
131     (_, (op1, op2)) = self._submitted.pop(0)
132     (_, (op3, )) = self._submitted.pop(0)
133     self.assertRaises(IndexError, self._submitted.pop)
134
135     for op in [op1, op2, op3]:
136       self.assertTrue("OP_TEST_DUMMY" in op.comment)
137       self.assertFalse(hasattr(op, "priority"))
138       self.assertFalse(hasattr(op, "debug_level"))
139
140   def testParams(self):
141     src = opcodes.OpTestDummy(priority=constants.OP_PRIO_HIGH,
142                               debug_level=3)
143
144     res = mcpu._ProcessResult(self._Submit, src, cmdlib.ResultWithJobs([[
145       opcodes.OpTestDelay(priority=constants.OP_PRIO_LOW),
146       ], [
147       opcodes.OpTestDelay(comment="foobar", debug_level=10),
148       ]], other=True, value=range(10)))
149
150     self.assertEqual(res, {
151       constants.JOB_IDS_KEY: [200, 201],
152       "other": True,
153       "value": range(10),
154       })
155
156     (_, (op1, )) = self._submitted.pop(0)
157     (_, (op2, )) = self._submitted.pop(0)
158     self.assertRaises(IndexError, self._submitted.pop)
159
160     self.assertEqual(op1.priority, constants.OP_PRIO_LOW)
161     self.assertTrue("OP_TEST_DUMMY" in op1.comment)
162     self.assertEqual(op1.debug_level, 3)
163
164     self.assertEqual(op2.priority, constants.OP_PRIO_HIGH)
165     self.assertEqual(op2.comment, "foobar")
166     self.assertEqual(op2.debug_level, 3)
167
168
169 if __name__ == "__main__":
170   testutils.GanetiTestProgram()