Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.opcodes_unittest.py @ 3ce9a5e7

History | View | Annotate | Download (9.9 kB)

1 c32b908e Michael Hanselmann
#!/usr/bin/python
2 c32b908e Michael Hanselmann
#
3 c32b908e Michael Hanselmann
4 687c10d9 Iustin Pop
# Copyright (C) 2010, 2011 Google Inc.
5 c32b908e Michael Hanselmann
#
6 c32b908e Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 c32b908e Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 c32b908e Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 c32b908e Michael Hanselmann
# (at your option) any later version.
10 c32b908e Michael Hanselmann
#
11 c32b908e Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 c32b908e Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 c32b908e Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 c32b908e Michael Hanselmann
# General Public License for more details.
15 c32b908e Michael Hanselmann
#
16 c32b908e Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 c32b908e Michael Hanselmann
# along with this program; if not, write to the Free Software
18 c32b908e Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 c32b908e Michael Hanselmann
# 02110-1301, USA.
20 c32b908e Michael Hanselmann
21 c32b908e Michael Hanselmann
22 c32b908e Michael Hanselmann
"""Script for testing ganeti.backend"""
23 c32b908e Michael Hanselmann
24 c32b908e Michael Hanselmann
import os
25 c32b908e Michael Hanselmann
import sys
26 c32b908e Michael Hanselmann
import unittest
27 c32b908e Michael Hanselmann
28 c32b908e Michael Hanselmann
from ganeti import utils
29 c32b908e Michael Hanselmann
from ganeti import opcodes
30 65e183af Michael Hanselmann
from ganeti import ht
31 1cbef6d8 Michael Hanselmann
from ganeti import constants
32 1cbef6d8 Michael Hanselmann
from ganeti import errors
33 45d4c81c Michael Hanselmann
from ganeti import compat
34 c32b908e Michael Hanselmann
35 c32b908e Michael Hanselmann
import testutils
36 c32b908e Michael Hanselmann
37 c32b908e Michael Hanselmann
38 c32b908e Michael Hanselmann
class TestOpcodes(unittest.TestCase):
39 c32b908e Michael Hanselmann
  def test(self):
40 c32b908e Michael Hanselmann
    self.assertRaises(ValueError, opcodes.OpCode.LoadOpCode, None)
41 c32b908e Michael Hanselmann
    self.assertRaises(ValueError, opcodes.OpCode.LoadOpCode, "")
42 c32b908e Michael Hanselmann
    self.assertRaises(ValueError, opcodes.OpCode.LoadOpCode, {})
43 c32b908e Michael Hanselmann
    self.assertRaises(ValueError, opcodes.OpCode.LoadOpCode, {"OP_ID": ""})
44 c32b908e Michael Hanselmann
45 c32b908e Michael Hanselmann
    for cls in opcodes.OP_MAPPING.values():
46 c32b908e Michael Hanselmann
      self.assert_(cls.OP_ID.startswith("OP_"))
47 dbc96028 Michael Hanselmann
      self.assert_(len(cls.OP_ID) > 3)
48 c32b908e Michael Hanselmann
      self.assertEqual(cls.OP_ID, cls.OP_ID.upper())
49 ff0d18e6 Iustin Pop
      self.assertEqual(cls.OP_ID, opcodes._NameToId(cls.__name__))
50 3ce9a5e7 Michael Hanselmann
      self.assertFalse(compat.any(cls.OP_ID.startswith(prefix)
51 3ce9a5e7 Michael Hanselmann
                                  for prefix in opcodes._SUMMARY_PREFIX.keys()))
52 c32b908e Michael Hanselmann
53 c32b908e Michael Hanselmann
      self.assertRaises(TypeError, cls, unsupported_parameter="some value")
54 c32b908e Michael Hanselmann
55 c32b908e Michael Hanselmann
      args = [
56 c32b908e Michael Hanselmann
        # No variables
57 c32b908e Michael Hanselmann
        {},
58 c32b908e Michael Hanselmann
59 c32b908e Michael Hanselmann
        # Variables supported by all opcodes
60 c32b908e Michael Hanselmann
        {"dry_run": False, "debug_level": 0, },
61 c32b908e Michael Hanselmann
62 c32b908e Michael Hanselmann
        # All variables
63 c32b908e Michael Hanselmann
        dict([(name, False) for name in cls._all_slots()])
64 c32b908e Michael Hanselmann
        ]
65 c32b908e Michael Hanselmann
66 c32b908e Michael Hanselmann
      for i in args:
67 c32b908e Michael Hanselmann
        op = cls(**i)
68 c32b908e Michael Hanselmann
69 c32b908e Michael Hanselmann
        self.assertEqual(op.OP_ID, cls.OP_ID)
70 c32b908e Michael Hanselmann
        self._checkSummary(op)
71 c32b908e Michael Hanselmann
72 c32b908e Michael Hanselmann
        # Try a restore
73 c32b908e Michael Hanselmann
        state = op.__getstate__()
74 c32b908e Michael Hanselmann
        self.assert_(isinstance(state, dict))
75 c32b908e Michael Hanselmann
76 c32b908e Michael Hanselmann
        restored = opcodes.OpCode.LoadOpCode(state)
77 c32b908e Michael Hanselmann
        self.assert_(isinstance(restored, cls))
78 c32b908e Michael Hanselmann
        self._checkSummary(restored)
79 c32b908e Michael Hanselmann
80 65e183af Michael Hanselmann
        for name in ["x_y_z", "hello_world"]:
81 65e183af Michael Hanselmann
          assert name not in cls._all_slots()
82 65e183af Michael Hanselmann
          for value in [None, True, False, [], "Hello World"]:
83 65e183af Michael Hanselmann
            self.assertRaises(AttributeError, setattr, op, name, value)
84 65e183af Michael Hanselmann
85 c32b908e Michael Hanselmann
  def _checkSummary(self, op):
86 c32b908e Michael Hanselmann
    summary = op.Summary()
87 c32b908e Michael Hanselmann
88 c32b908e Michael Hanselmann
    if hasattr(op, "OP_DSC_FIELD"):
89 c32b908e Michael Hanselmann
      self.assert_(("OP_%s" % summary).startswith("%s(" % op.OP_ID))
90 c32b908e Michael Hanselmann
      self.assert_(summary.endswith(")"))
91 c32b908e Michael Hanselmann
    else:
92 c32b908e Michael Hanselmann
      self.assertEqual("OP_%s" % summary, op.OP_ID)
93 c32b908e Michael Hanselmann
94 65ffb373 Michael Hanselmann
  def testSummary(self):
95 ff0d18e6 Iustin Pop
    class OpTest(opcodes.OpCode):
96 65ffb373 Michael Hanselmann
      OP_DSC_FIELD = "data"
97 65ffb373 Michael Hanselmann
      OP_PARAMS = [
98 197b323b Michael Hanselmann
        ("data", ht.NoDefault, ht.TString, None),
99 65ffb373 Michael Hanselmann
        ]
100 65ffb373 Michael Hanselmann
101 ff0d18e6 Iustin Pop
    self.assertEqual(OpTest(data="").Summary(), "TEST()")
102 ff0d18e6 Iustin Pop
    self.assertEqual(OpTest(data="Hello World").Summary(),
103 65ffb373 Michael Hanselmann
                     "TEST(Hello World)")
104 ff0d18e6 Iustin Pop
    self.assertEqual(OpTest(data="node1.example.com").Summary(),
105 65ffb373 Michael Hanselmann
                     "TEST(node1.example.com)")
106 65ffb373 Michael Hanselmann
107 3ce9a5e7 Michael Hanselmann
  def testTinySummary(self):
108 3ce9a5e7 Michael Hanselmann
    self.assertFalse(utils.FindDuplicates(opcodes._SUMMARY_PREFIX.values()))
109 3ce9a5e7 Michael Hanselmann
    self.assertTrue(compat.all(prefix.endswith("_") and supplement.endswith("_")
110 3ce9a5e7 Michael Hanselmann
                               for (prefix, supplement) in
111 3ce9a5e7 Michael Hanselmann
                                 opcodes._SUMMARY_PREFIX.items()))
112 3ce9a5e7 Michael Hanselmann
113 3ce9a5e7 Michael Hanselmann
    self.assertEqual(opcodes.OpClusterPostInit().TinySummary(), "C_POST_INIT")
114 3ce9a5e7 Michael Hanselmann
    self.assertEqual(opcodes.OpNodeRemove().TinySummary(), "N_REMOVE")
115 3ce9a5e7 Michael Hanselmann
    self.assertEqual(opcodes.OpInstanceMigrate().TinySummary(), "I_MIGRATE")
116 3ce9a5e7 Michael Hanselmann
    self.assertEqual(opcodes.OpGroupQuery().TinySummary(), "G_QUERY")
117 3ce9a5e7 Michael Hanselmann
    self.assertEqual(opcodes.OpTestJqueue().TinySummary(), "TEST_JQUEUE")
118 3ce9a5e7 Michael Hanselmann
119 65ffb373 Michael Hanselmann
  def testListSummary(self):
120 ff0d18e6 Iustin Pop
    class OpTest(opcodes.OpCode):
121 65ffb373 Michael Hanselmann
      OP_DSC_FIELD = "data"
122 65ffb373 Michael Hanselmann
      OP_PARAMS = [
123 197b323b Michael Hanselmann
        ("data", ht.NoDefault, ht.TList, None),
124 65ffb373 Michael Hanselmann
        ]
125 65ffb373 Michael Hanselmann
126 ff0d18e6 Iustin Pop
    self.assertEqual(OpTest(data=["a", "b", "c"]).Summary(),
127 65ffb373 Michael Hanselmann
                     "TEST(a,b,c)")
128 ff0d18e6 Iustin Pop
    self.assertEqual(OpTest(data=["a", None, "c"]).Summary(),
129 65ffb373 Michael Hanselmann
                     "TEST(a,None,c)")
130 ff0d18e6 Iustin Pop
    self.assertEqual(OpTest(data=[1, 2, 3, 4]).Summary(), "TEST(1,2,3,4)")
131 65ffb373 Michael Hanselmann
132 dbc96028 Michael Hanselmann
  def testOpId(self):
133 dbc96028 Michael Hanselmann
    self.assertFalse(utils.FindDuplicates(cls.OP_ID
134 dbc96028 Michael Hanselmann
                                          for cls in opcodes._GetOpList()))
135 dbc96028 Michael Hanselmann
    self.assertEqual(len(opcodes._GetOpList()), len(opcodes.OP_MAPPING))
136 dbc96028 Michael Hanselmann
137 65e183af Michael Hanselmann
  def testParams(self):
138 65e183af Michael Hanselmann
    supported_by_all = set(["debug_level", "dry_run", "priority"])
139 65e183af Michael Hanselmann
140 687c10d9 Iustin Pop
    self.assertTrue(opcodes.BaseOpCode not in opcodes.OP_MAPPING.values())
141 687c10d9 Iustin Pop
    self.assertTrue(opcodes.OpCode not in opcodes.OP_MAPPING.values())
142 65e183af Michael Hanselmann
143 687c10d9 Iustin Pop
    for cls in opcodes.OP_MAPPING.values() + [opcodes.OpCode]:
144 65e183af Michael Hanselmann
      all_slots = cls._all_slots()
145 65e183af Michael Hanselmann
146 65e183af Michael Hanselmann
      self.assertEqual(len(set(all_slots) & supported_by_all), 3,
147 65e183af Michael Hanselmann
                       msg=("Opcode %s doesn't support all base"
148 65e183af Michael Hanselmann
                            " parameters (%r)" % (cls.OP_ID, supported_by_all)))
149 65e183af Michael Hanselmann
150 65e183af Michael Hanselmann
      # All opcodes must have OP_PARAMS
151 65e183af Michael Hanselmann
      self.assert_(hasattr(cls, "OP_PARAMS"),
152 65e183af Michael Hanselmann
                   msg="%s doesn't have OP_PARAMS" % cls.OP_ID)
153 65e183af Michael Hanselmann
154 197b323b Michael Hanselmann
      param_names = [name for (name, _, _, _) in cls.GetAllParams()]
155 65e183af Michael Hanselmann
156 65e183af Michael Hanselmann
      self.assertEqual(all_slots, param_names)
157 65e183af Michael Hanselmann
158 65e183af Michael Hanselmann
      # Without inheritance
159 197b323b Michael Hanselmann
      self.assertEqual(cls.__slots__,
160 197b323b Michael Hanselmann
                       [name for (name, _, _, _) in cls.OP_PARAMS])
161 65e183af Michael Hanselmann
162 65e183af Michael Hanselmann
      # This won't work if parameters are converted to a dictionary
163 65e183af Michael Hanselmann
      duplicates = utils.FindDuplicates(param_names)
164 65e183af Michael Hanselmann
      self.assertFalse(duplicates,
165 65e183af Michael Hanselmann
                       msg=("Found duplicate parameters %r in %s" %
166 65e183af Michael Hanselmann
                            (duplicates, cls.OP_ID)))
167 65e183af Michael Hanselmann
168 65e183af Michael Hanselmann
      # Check parameter definitions
169 197b323b Michael Hanselmann
      for attr_name, aval, test, doc in cls.GetAllParams():
170 65e183af Michael Hanselmann
        self.assert_(attr_name)
171 65e183af Michael Hanselmann
        self.assert_(test is None or test is ht.NoType or callable(test),
172 65e183af Michael Hanselmann
                     msg=("Invalid type check for %s.%s" %
173 65e183af Michael Hanselmann
                          (cls.OP_ID, attr_name)))
174 45d4c81c Michael Hanselmann
        self.assertTrue(doc is None or isinstance(doc, basestring))
175 65e183af Michael Hanselmann
176 65e183af Michael Hanselmann
        if callable(aval):
177 65e183af Michael Hanselmann
          self.assertFalse(callable(aval()),
178 65e183af Michael Hanselmann
                           msg="Default value returned by function is callable")
179 65e183af Michael Hanselmann
180 45d4c81c Michael Hanselmann
      # If any parameter has documentation, all others need to have it as well
181 45d4c81c Michael Hanselmann
      has_doc = [doc is not None for (_, _, _, doc) in cls.OP_PARAMS]
182 45d4c81c Michael Hanselmann
      self.assertTrue(not compat.any(has_doc) or compat.all(has_doc),
183 45d4c81c Michael Hanselmann
                      msg="%s does not document all parameters" % cls)
184 45d4c81c Michael Hanselmann
185 1cbef6d8 Michael Hanselmann
  def testValidateNoModification(self):
186 ff0d18e6 Iustin Pop
    class OpTest(opcodes.OpCode):
187 1cbef6d8 Michael Hanselmann
      OP_PARAMS = [
188 197b323b Michael Hanselmann
        ("nodef", ht.NoDefault, ht.TMaybeString, None),
189 197b323b Michael Hanselmann
        ("wdef", "default", ht.TMaybeString, None),
190 197b323b Michael Hanselmann
        ("number", 0, ht.TInt, None),
191 197b323b Michael Hanselmann
        ("notype", None, ht.NoType, None),
192 1cbef6d8 Michael Hanselmann
        ]
193 1cbef6d8 Michael Hanselmann
194 1cbef6d8 Michael Hanselmann
    # Missing required parameter "nodef"
195 ff0d18e6 Iustin Pop
    op = OpTest()
196 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
197 1cbef6d8 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, op.Validate, False)
198 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "nodef"))
199 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "wdef"))
200 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "number"))
201 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "notype"))
202 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
203 1cbef6d8 Michael Hanselmann
204 1cbef6d8 Michael Hanselmann
    # Required parameter "nodef" is provided
205 ff0d18e6 Iustin Pop
    op = OpTest(nodef="foo")
206 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
207 1cbef6d8 Michael Hanselmann
    op.Validate(False)
208 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
209 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.nodef, "foo")
210 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "wdef"))
211 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "number"))
212 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "notype"))
213 1cbef6d8 Michael Hanselmann
214 1cbef6d8 Michael Hanselmann
    # Missing required parameter "nodef"
215 ff0d18e6 Iustin Pop
    op = OpTest(wdef="hello", number=999)
216 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
217 1cbef6d8 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, op.Validate, False)
218 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "nodef"))
219 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "notype"))
220 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
221 1cbef6d8 Michael Hanselmann
222 1cbef6d8 Michael Hanselmann
    # Wrong type for "nodef"
223 ff0d18e6 Iustin Pop
    op = OpTest(nodef=987)
224 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
225 1cbef6d8 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, op.Validate, False)
226 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.nodef, 987)
227 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "notype"))
228 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
229 1cbef6d8 Michael Hanselmann
230 1cbef6d8 Michael Hanselmann
    # Testing different types for "notype"
231 ff0d18e6 Iustin Pop
    op = OpTest(nodef="foo", notype=[1, 2, 3])
232 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
233 1cbef6d8 Michael Hanselmann
    op.Validate(False)
234 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.nodef, "foo")
235 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.notype, [1, 2, 3])
236 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
237 1cbef6d8 Michael Hanselmann
238 ff0d18e6 Iustin Pop
    op = OpTest(nodef="foo", notype="Hello World")
239 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
240 1cbef6d8 Michael Hanselmann
    op.Validate(False)
241 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.nodef, "foo")
242 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.notype, "Hello World")
243 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
244 1cbef6d8 Michael Hanselmann
245 1cbef6d8 Michael Hanselmann
  def testValidateSetDefaults(self):
246 ff0d18e6 Iustin Pop
    class OpTest(opcodes.OpCode):
247 1cbef6d8 Michael Hanselmann
      OP_PARAMS = [
248 1cbef6d8 Michael Hanselmann
        # Static default value
249 197b323b Michael Hanselmann
        ("value1", "default", ht.TMaybeString, None),
250 1cbef6d8 Michael Hanselmann
251 1cbef6d8 Michael Hanselmann
        # Default value callback
252 197b323b Michael Hanselmann
        ("value2", lambda: "result", ht.TMaybeString, None),
253 1cbef6d8 Michael Hanselmann
        ]
254 1cbef6d8 Michael Hanselmann
255 ff0d18e6 Iustin Pop
    op = OpTest()
256 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
257 1cbef6d8 Michael Hanselmann
    op.Validate(True)
258 1cbef6d8 Michael Hanselmann
    self.assertNotEqual(op.__getstate__(), before,
259 1cbef6d8 Michael Hanselmann
                        msg="Opcode was not modified")
260 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.value1, "default")
261 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.value2, "result")
262 1cbef6d8 Michael Hanselmann
    self.assert_(op.dry_run is None)
263 1cbef6d8 Michael Hanselmann
    self.assert_(op.debug_level is None)
264 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.priority, constants.OP_PRIO_DEFAULT)
265 1cbef6d8 Michael Hanselmann
266 ff0d18e6 Iustin Pop
    op = OpTest(value1="hello", value2="world", debug_level=123)
267 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
268 1cbef6d8 Michael Hanselmann
    op.Validate(True)
269 1cbef6d8 Michael Hanselmann
    self.assertNotEqual(op.__getstate__(), before,
270 1cbef6d8 Michael Hanselmann
                        msg="Opcode was not modified")
271 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.value1, "hello")
272 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.value2, "world")
273 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.debug_level, 123)
274 1cbef6d8 Michael Hanselmann
275 c32b908e Michael Hanselmann
276 c32b908e Michael Hanselmann
if __name__ == "__main__":
277 c32b908e Michael Hanselmann
  testutils.GanetiTestProgram()