Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.opcodes_unittest.py @ fb0be379

History | View | Annotate | Download (9.1 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 c32b908e Michael Hanselmann
51 c32b908e Michael Hanselmann
      self.assertRaises(TypeError, cls, unsupported_parameter="some value")
52 c32b908e Michael Hanselmann
53 c32b908e Michael Hanselmann
      args = [
54 c32b908e Michael Hanselmann
        # No variables
55 c32b908e Michael Hanselmann
        {},
56 c32b908e Michael Hanselmann
57 c32b908e Michael Hanselmann
        # Variables supported by all opcodes
58 c32b908e Michael Hanselmann
        {"dry_run": False, "debug_level": 0, },
59 c32b908e Michael Hanselmann
60 c32b908e Michael Hanselmann
        # All variables
61 c32b908e Michael Hanselmann
        dict([(name, False) for name in cls._all_slots()])
62 c32b908e Michael Hanselmann
        ]
63 c32b908e Michael Hanselmann
64 c32b908e Michael Hanselmann
      for i in args:
65 c32b908e Michael Hanselmann
        op = cls(**i)
66 c32b908e Michael Hanselmann
67 c32b908e Michael Hanselmann
        self.assertEqual(op.OP_ID, cls.OP_ID)
68 c32b908e Michael Hanselmann
        self._checkSummary(op)
69 c32b908e Michael Hanselmann
70 c32b908e Michael Hanselmann
        # Try a restore
71 c32b908e Michael Hanselmann
        state = op.__getstate__()
72 c32b908e Michael Hanselmann
        self.assert_(isinstance(state, dict))
73 c32b908e Michael Hanselmann
74 c32b908e Michael Hanselmann
        restored = opcodes.OpCode.LoadOpCode(state)
75 c32b908e Michael Hanselmann
        self.assert_(isinstance(restored, cls))
76 c32b908e Michael Hanselmann
        self._checkSummary(restored)
77 c32b908e Michael Hanselmann
78 65e183af Michael Hanselmann
        for name in ["x_y_z", "hello_world"]:
79 65e183af Michael Hanselmann
          assert name not in cls._all_slots()
80 65e183af Michael Hanselmann
          for value in [None, True, False, [], "Hello World"]:
81 65e183af Michael Hanselmann
            self.assertRaises(AttributeError, setattr, op, name, value)
82 65e183af Michael Hanselmann
83 c32b908e Michael Hanselmann
  def _checkSummary(self, op):
84 c32b908e Michael Hanselmann
    summary = op.Summary()
85 c32b908e Michael Hanselmann
86 c32b908e Michael Hanselmann
    if hasattr(op, "OP_DSC_FIELD"):
87 c32b908e Michael Hanselmann
      self.assert_(("OP_%s" % summary).startswith("%s(" % op.OP_ID))
88 c32b908e Michael Hanselmann
      self.assert_(summary.endswith(")"))
89 c32b908e Michael Hanselmann
    else:
90 c32b908e Michael Hanselmann
      self.assertEqual("OP_%s" % summary, op.OP_ID)
91 c32b908e Michael Hanselmann
92 65ffb373 Michael Hanselmann
  def testSummary(self):
93 ff0d18e6 Iustin Pop
    class OpTest(opcodes.OpCode):
94 65ffb373 Michael Hanselmann
      OP_DSC_FIELD = "data"
95 65ffb373 Michael Hanselmann
      OP_PARAMS = [
96 197b323b Michael Hanselmann
        ("data", ht.NoDefault, ht.TString, None),
97 65ffb373 Michael Hanselmann
        ]
98 65ffb373 Michael Hanselmann
99 ff0d18e6 Iustin Pop
    self.assertEqual(OpTest(data="").Summary(), "TEST()")
100 ff0d18e6 Iustin Pop
    self.assertEqual(OpTest(data="Hello World").Summary(),
101 65ffb373 Michael Hanselmann
                     "TEST(Hello World)")
102 ff0d18e6 Iustin Pop
    self.assertEqual(OpTest(data="node1.example.com").Summary(),
103 65ffb373 Michael Hanselmann
                     "TEST(node1.example.com)")
104 65ffb373 Michael Hanselmann
105 65ffb373 Michael Hanselmann
  def testListSummary(self):
106 ff0d18e6 Iustin Pop
    class OpTest(opcodes.OpCode):
107 65ffb373 Michael Hanselmann
      OP_DSC_FIELD = "data"
108 65ffb373 Michael Hanselmann
      OP_PARAMS = [
109 197b323b Michael Hanselmann
        ("data", ht.NoDefault, ht.TList, None),
110 65ffb373 Michael Hanselmann
        ]
111 65ffb373 Michael Hanselmann
112 ff0d18e6 Iustin Pop
    self.assertEqual(OpTest(data=["a", "b", "c"]).Summary(),
113 65ffb373 Michael Hanselmann
                     "TEST(a,b,c)")
114 ff0d18e6 Iustin Pop
    self.assertEqual(OpTest(data=["a", None, "c"]).Summary(),
115 65ffb373 Michael Hanselmann
                     "TEST(a,None,c)")
116 ff0d18e6 Iustin Pop
    self.assertEqual(OpTest(data=[1, 2, 3, 4]).Summary(), "TEST(1,2,3,4)")
117 65ffb373 Michael Hanselmann
118 dbc96028 Michael Hanselmann
  def testOpId(self):
119 dbc96028 Michael Hanselmann
    self.assertFalse(utils.FindDuplicates(cls.OP_ID
120 dbc96028 Michael Hanselmann
                                          for cls in opcodes._GetOpList()))
121 dbc96028 Michael Hanselmann
    self.assertEqual(len(opcodes._GetOpList()), len(opcodes.OP_MAPPING))
122 dbc96028 Michael Hanselmann
123 65e183af Michael Hanselmann
  def testParams(self):
124 65e183af Michael Hanselmann
    supported_by_all = set(["debug_level", "dry_run", "priority"])
125 65e183af Michael Hanselmann
126 687c10d9 Iustin Pop
    self.assertTrue(opcodes.BaseOpCode not in opcodes.OP_MAPPING.values())
127 687c10d9 Iustin Pop
    self.assertTrue(opcodes.OpCode not in opcodes.OP_MAPPING.values())
128 65e183af Michael Hanselmann
129 687c10d9 Iustin Pop
    for cls in opcodes.OP_MAPPING.values() + [opcodes.OpCode]:
130 65e183af Michael Hanselmann
      all_slots = cls._all_slots()
131 65e183af Michael Hanselmann
132 65e183af Michael Hanselmann
      self.assertEqual(len(set(all_slots) & supported_by_all), 3,
133 65e183af Michael Hanselmann
                       msg=("Opcode %s doesn't support all base"
134 65e183af Michael Hanselmann
                            " parameters (%r)" % (cls.OP_ID, supported_by_all)))
135 65e183af Michael Hanselmann
136 65e183af Michael Hanselmann
      # All opcodes must have OP_PARAMS
137 65e183af Michael Hanselmann
      self.assert_(hasattr(cls, "OP_PARAMS"),
138 65e183af Michael Hanselmann
                   msg="%s doesn't have OP_PARAMS" % cls.OP_ID)
139 65e183af Michael Hanselmann
140 197b323b Michael Hanselmann
      param_names = [name for (name, _, _, _) in cls.GetAllParams()]
141 65e183af Michael Hanselmann
142 65e183af Michael Hanselmann
      self.assertEqual(all_slots, param_names)
143 65e183af Michael Hanselmann
144 65e183af Michael Hanselmann
      # Without inheritance
145 197b323b Michael Hanselmann
      self.assertEqual(cls.__slots__,
146 197b323b Michael Hanselmann
                       [name for (name, _, _, _) in cls.OP_PARAMS])
147 65e183af Michael Hanselmann
148 65e183af Michael Hanselmann
      # This won't work if parameters are converted to a dictionary
149 65e183af Michael Hanselmann
      duplicates = utils.FindDuplicates(param_names)
150 65e183af Michael Hanselmann
      self.assertFalse(duplicates,
151 65e183af Michael Hanselmann
                       msg=("Found duplicate parameters %r in %s" %
152 65e183af Michael Hanselmann
                            (duplicates, cls.OP_ID)))
153 65e183af Michael Hanselmann
154 65e183af Michael Hanselmann
      # Check parameter definitions
155 197b323b Michael Hanselmann
      for attr_name, aval, test, doc in cls.GetAllParams():
156 65e183af Michael Hanselmann
        self.assert_(attr_name)
157 65e183af Michael Hanselmann
        self.assert_(test is None or test is ht.NoType or callable(test),
158 65e183af Michael Hanselmann
                     msg=("Invalid type check for %s.%s" %
159 65e183af Michael Hanselmann
                          (cls.OP_ID, attr_name)))
160 45d4c81c Michael Hanselmann
        self.assertTrue(doc is None or isinstance(doc, basestring))
161 65e183af Michael Hanselmann
162 65e183af Michael Hanselmann
        if callable(aval):
163 65e183af Michael Hanselmann
          self.assertFalse(callable(aval()),
164 65e183af Michael Hanselmann
                           msg="Default value returned by function is callable")
165 65e183af Michael Hanselmann
166 45d4c81c Michael Hanselmann
      # If any parameter has documentation, all others need to have it as well
167 45d4c81c Michael Hanselmann
      has_doc = [doc is not None for (_, _, _, doc) in cls.OP_PARAMS]
168 45d4c81c Michael Hanselmann
      self.assertTrue(not compat.any(has_doc) or compat.all(has_doc),
169 45d4c81c Michael Hanselmann
                      msg="%s does not document all parameters" % cls)
170 45d4c81c Michael Hanselmann
171 1cbef6d8 Michael Hanselmann
  def testValidateNoModification(self):
172 ff0d18e6 Iustin Pop
    class OpTest(opcodes.OpCode):
173 1cbef6d8 Michael Hanselmann
      OP_PARAMS = [
174 197b323b Michael Hanselmann
        ("nodef", ht.NoDefault, ht.TMaybeString, None),
175 197b323b Michael Hanselmann
        ("wdef", "default", ht.TMaybeString, None),
176 197b323b Michael Hanselmann
        ("number", 0, ht.TInt, None),
177 197b323b Michael Hanselmann
        ("notype", None, ht.NoType, None),
178 1cbef6d8 Michael Hanselmann
        ]
179 1cbef6d8 Michael Hanselmann
180 1cbef6d8 Michael Hanselmann
    # Missing required parameter "nodef"
181 ff0d18e6 Iustin Pop
    op = OpTest()
182 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
183 1cbef6d8 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, op.Validate, False)
184 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "nodef"))
185 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "wdef"))
186 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "number"))
187 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "notype"))
188 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
189 1cbef6d8 Michael Hanselmann
190 1cbef6d8 Michael Hanselmann
    # Required parameter "nodef" is provided
191 ff0d18e6 Iustin Pop
    op = OpTest(nodef="foo")
192 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
193 1cbef6d8 Michael Hanselmann
    op.Validate(False)
194 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
195 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.nodef, "foo")
196 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "wdef"))
197 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "number"))
198 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "notype"))
199 1cbef6d8 Michael Hanselmann
200 1cbef6d8 Michael Hanselmann
    # Missing required parameter "nodef"
201 ff0d18e6 Iustin Pop
    op = OpTest(wdef="hello", number=999)
202 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
203 1cbef6d8 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, op.Validate, False)
204 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "nodef"))
205 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "notype"))
206 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
207 1cbef6d8 Michael Hanselmann
208 1cbef6d8 Michael Hanselmann
    # Wrong type for "nodef"
209 ff0d18e6 Iustin Pop
    op = OpTest(nodef=987)
210 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
211 1cbef6d8 Michael Hanselmann
    self.assertRaises(errors.OpPrereqError, op.Validate, False)
212 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.nodef, 987)
213 1cbef6d8 Michael Hanselmann
    self.assertFalse(hasattr(op, "notype"))
214 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
215 1cbef6d8 Michael Hanselmann
216 1cbef6d8 Michael Hanselmann
    # Testing different types for "notype"
217 ff0d18e6 Iustin Pop
    op = OpTest(nodef="foo", notype=[1, 2, 3])
218 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
219 1cbef6d8 Michael Hanselmann
    op.Validate(False)
220 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.nodef, "foo")
221 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.notype, [1, 2, 3])
222 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
223 1cbef6d8 Michael Hanselmann
224 ff0d18e6 Iustin Pop
    op = OpTest(nodef="foo", notype="Hello World")
225 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
226 1cbef6d8 Michael Hanselmann
    op.Validate(False)
227 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.nodef, "foo")
228 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.notype, "Hello World")
229 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.__getstate__(), before, msg="Opcode was modified")
230 1cbef6d8 Michael Hanselmann
231 1cbef6d8 Michael Hanselmann
  def testValidateSetDefaults(self):
232 ff0d18e6 Iustin Pop
    class OpTest(opcodes.OpCode):
233 1cbef6d8 Michael Hanselmann
      OP_PARAMS = [
234 1cbef6d8 Michael Hanselmann
        # Static default value
235 197b323b Michael Hanselmann
        ("value1", "default", ht.TMaybeString, None),
236 1cbef6d8 Michael Hanselmann
237 1cbef6d8 Michael Hanselmann
        # Default value callback
238 197b323b Michael Hanselmann
        ("value2", lambda: "result", ht.TMaybeString, None),
239 1cbef6d8 Michael Hanselmann
        ]
240 1cbef6d8 Michael Hanselmann
241 ff0d18e6 Iustin Pop
    op = OpTest()
242 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
243 1cbef6d8 Michael Hanselmann
    op.Validate(True)
244 1cbef6d8 Michael Hanselmann
    self.assertNotEqual(op.__getstate__(), before,
245 1cbef6d8 Michael Hanselmann
                        msg="Opcode was not modified")
246 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.value1, "default")
247 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.value2, "result")
248 1cbef6d8 Michael Hanselmann
    self.assert_(op.dry_run is None)
249 1cbef6d8 Michael Hanselmann
    self.assert_(op.debug_level is None)
250 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.priority, constants.OP_PRIO_DEFAULT)
251 1cbef6d8 Michael Hanselmann
252 ff0d18e6 Iustin Pop
    op = OpTest(value1="hello", value2="world", debug_level=123)
253 1cbef6d8 Michael Hanselmann
    before = op.__getstate__()
254 1cbef6d8 Michael Hanselmann
    op.Validate(True)
255 1cbef6d8 Michael Hanselmann
    self.assertNotEqual(op.__getstate__(), before,
256 1cbef6d8 Michael Hanselmann
                        msg="Opcode was not modified")
257 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.value1, "hello")
258 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.value2, "world")
259 1cbef6d8 Michael Hanselmann
    self.assertEqual(op.debug_level, 123)
260 1cbef6d8 Michael Hanselmann
261 c32b908e Michael Hanselmann
262 c32b908e Michael Hanselmann
if __name__ == "__main__":
263 c32b908e Michael Hanselmann
  testutils.GanetiTestProgram()