root / test / py / qa.qa_config_unittest.py @ 6a654276
History | View | Annotate | Download (8.4 kB)
1 |
#!/usr/bin/python
|
---|---|
2 |
#
|
3 |
|
4 |
# Copyright (C) 2012, 2013 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 testing qa.qa_config"""
|
23 |
|
24 |
import unittest |
25 |
import tempfile |
26 |
import shutil |
27 |
import os |
28 |
import operator |
29 |
|
30 |
from ganeti import utils |
31 |
from ganeti import serializer |
32 |
from ganeti import constants |
33 |
from ganeti import compat |
34 |
|
35 |
from qa import qa_config |
36 |
from qa import qa_error |
37 |
|
38 |
import testutils |
39 |
|
40 |
|
41 |
class TestTestEnabled(unittest.TestCase): |
42 |
def testSimple(self): |
43 |
for name in ["test", ["foobar"], ["a", "b"]]: |
44 |
self.assertTrue(qa_config.TestEnabled(name, _cfg={}))
|
45 |
|
46 |
for default in [False, True]: |
47 |
self.assertFalse(qa_config.TestEnabled("foo", _cfg={ |
48 |
"tests": {
|
49 |
"default": default,
|
50 |
"foo": False, |
51 |
}, |
52 |
})) |
53 |
|
54 |
self.assertTrue(qa_config.TestEnabled("bar", _cfg={ |
55 |
"tests": {
|
56 |
"default": default,
|
57 |
"bar": True, |
58 |
}, |
59 |
})) |
60 |
|
61 |
def testEitherWithDefault(self): |
62 |
names = qa_config.Either("one")
|
63 |
|
64 |
self.assertTrue(qa_config.TestEnabled(names, _cfg={
|
65 |
"tests": {
|
66 |
"default": True, |
67 |
}, |
68 |
})) |
69 |
|
70 |
self.assertFalse(qa_config.TestEnabled(names, _cfg={
|
71 |
"tests": {
|
72 |
"default": False, |
73 |
}, |
74 |
})) |
75 |
|
76 |
def testEither(self): |
77 |
names = [qa_config.Either(["one", "two"]), |
78 |
qa_config.Either("foo"),
|
79 |
"hello",
|
80 |
["bar", "baz"]] |
81 |
|
82 |
self.assertTrue(qa_config.TestEnabled(names, _cfg={
|
83 |
"tests": {
|
84 |
"default": True, |
85 |
}, |
86 |
})) |
87 |
|
88 |
self.assertFalse(qa_config.TestEnabled(names, _cfg={
|
89 |
"tests": {
|
90 |
"default": False, |
91 |
}, |
92 |
})) |
93 |
|
94 |
for name in ["foo", "bar", "baz", "hello"]: |
95 |
self.assertFalse(qa_config.TestEnabled(names, _cfg={
|
96 |
"tests": {
|
97 |
"default": True, |
98 |
name: False,
|
99 |
}, |
100 |
})) |
101 |
|
102 |
self.assertFalse(qa_config.TestEnabled(names, _cfg={
|
103 |
"tests": {
|
104 |
"default": True, |
105 |
"one": False, |
106 |
"two": False, |
107 |
}, |
108 |
})) |
109 |
|
110 |
self.assertTrue(qa_config.TestEnabled(names, _cfg={
|
111 |
"tests": {
|
112 |
"default": True, |
113 |
"one": False, |
114 |
"two": True, |
115 |
}, |
116 |
})) |
117 |
|
118 |
self.assertFalse(qa_config.TestEnabled(names, _cfg={
|
119 |
"tests": {
|
120 |
"default": True, |
121 |
"one": True, |
122 |
"two": True, |
123 |
"foo": False, |
124 |
}, |
125 |
})) |
126 |
|
127 |
def testEitherNestedWithAnd(self): |
128 |
names = qa_config.Either([["one", "two"], "foo"]) |
129 |
|
130 |
self.assertTrue(qa_config.TestEnabled(names, _cfg={
|
131 |
"tests": {
|
132 |
"default": True, |
133 |
}, |
134 |
})) |
135 |
|
136 |
for name in ["one", "two"]: |
137 |
self.assertFalse(qa_config.TestEnabled(names, _cfg={
|
138 |
"tests": {
|
139 |
"default": True, |
140 |
"foo": False, |
141 |
name: False,
|
142 |
}, |
143 |
})) |
144 |
|
145 |
|
146 |
class TestQaConfigLoad(unittest.TestCase): |
147 |
def setUp(self): |
148 |
self.tmpdir = tempfile.mkdtemp()
|
149 |
|
150 |
def tearDown(self): |
151 |
shutil.rmtree(self.tmpdir)
|
152 |
|
153 |
def testLoadNonExistent(self): |
154 |
filename = utils.PathJoin(self.tmpdir, "does.not.exist") |
155 |
self.assertRaises(EnvironmentError, qa_config._QaConfig.Load, filename) |
156 |
|
157 |
@staticmethod
|
158 |
def _WriteConfig(filename, data): |
159 |
utils.WriteFile(filename, data=serializer.DumpJson(data)) |
160 |
|
161 |
def _CheckLoadError(self, filename, data, expected): |
162 |
self._WriteConfig(filename, data)
|
163 |
|
164 |
try:
|
165 |
qa_config._QaConfig.Load(filename) |
166 |
except qa_error.Error, err:
|
167 |
self.assertTrue(str(err).startswith(expected)) |
168 |
else:
|
169 |
self.fail("Exception was not raised") |
170 |
|
171 |
def testFailsValidation(self): |
172 |
filename = utils.PathJoin(self.tmpdir, "qa.json") |
173 |
testconfig = {} |
174 |
|
175 |
check_fn = compat.partial(self._CheckLoadError, filename, testconfig)
|
176 |
|
177 |
# No nodes
|
178 |
check_fn("Need at least one node")
|
179 |
|
180 |
testconfig["nodes"] = [
|
181 |
{ |
182 |
"primary": "xen-test-0", |
183 |
"secondary": "192.0.2.1", |
184 |
}, |
185 |
] |
186 |
|
187 |
# No instances
|
188 |
check_fn("Need at least one instance")
|
189 |
|
190 |
testconfig["instances"] = [
|
191 |
{ |
192 |
"name": "xen-test-inst1", |
193 |
}, |
194 |
] |
195 |
|
196 |
# Missing "disk" and "disk-growth"
|
197 |
check_fn("Config options 'disk' and 'disk-growth' ")
|
198 |
|
199 |
testconfig["disk"] = []
|
200 |
testconfig["disk-growth"] = testconfig["disk"] |
201 |
|
202 |
# Minimal accepted configuration
|
203 |
self._WriteConfig(filename, testconfig)
|
204 |
result = qa_config._QaConfig.Load(filename) |
205 |
self.assertTrue(result.get("nodes")) |
206 |
|
207 |
# Non-existent instance check script
|
208 |
testconfig[qa_config._INSTANCE_CHECK_KEY] = \ |
209 |
utils.PathJoin(self.tmpdir, "instcheck") |
210 |
check_fn("Can't find instance check script")
|
211 |
del testconfig[qa_config._INSTANCE_CHECK_KEY]
|
212 |
|
213 |
# No enabled hypervisor
|
214 |
testconfig[qa_config._ENABLED_HV_KEY] = None
|
215 |
check_fn("No hypervisor is enabled")
|
216 |
|
217 |
# Unknown hypervisor
|
218 |
testconfig[qa_config._ENABLED_HV_KEY] = ["#unknownhv#"]
|
219 |
check_fn("Unknown hypervisor(s) enabled:")
|
220 |
|
221 |
|
222 |
class TestQaConfigWithSampleConfig(unittest.TestCase): |
223 |
"""Tests using C{qa-sample.json}.
|
224 |
|
225 |
This test case serves two purposes:
|
226 |
|
227 |
- Ensure shipped C{qa-sample.json} file is considered a valid QA
|
228 |
configuration
|
229 |
- Test some functions of L{qa_config._QaConfig} without having to
|
230 |
mock a whole configuration file
|
231 |
|
232 |
"""
|
233 |
def setUp(self): |
234 |
filename = "%s/qa/qa-sample.json" % testutils.GetSourceDir()
|
235 |
|
236 |
self.config = qa_config._QaConfig.Load(filename)
|
237 |
|
238 |
def testGetEnabledHypervisors(self): |
239 |
self.assertEqual(self.config.GetEnabledHypervisors(), |
240 |
[constants.DEFAULT_ENABLED_HYPERVISOR]) |
241 |
|
242 |
def testGetDefaultHypervisor(self): |
243 |
self.assertEqual(self.config.GetDefaultHypervisor(), |
244 |
constants.DEFAULT_ENABLED_HYPERVISOR) |
245 |
|
246 |
def testGetInstanceCheckScript(self): |
247 |
self.assertTrue(self.config.GetInstanceCheckScript() is None) |
248 |
|
249 |
def testGetAndGetItem(self): |
250 |
self.assertEqual(self.config["nodes"], self.config.get("nodes")) |
251 |
|
252 |
def testGetMasterNode(self): |
253 |
self.assertEqual(self.config.GetMasterNode(), self.config["nodes"][0]) |
254 |
|
255 |
|
256 |
class TestQaConfig(unittest.TestCase): |
257 |
def setUp(self): |
258 |
filename = \ |
259 |
testutils.TestDataFilename("qa-minimal-nodes-instances-only.json")
|
260 |
|
261 |
self.config = qa_config._QaConfig.Load(filename)
|
262 |
|
263 |
def testExclusiveStorage(self): |
264 |
self.assertRaises(AssertionError, self.config.GetExclusiveStorage) |
265 |
|
266 |
for value in [False, True, 0, 1, 30804, ""]: |
267 |
self.config.SetExclusiveStorage(value)
|
268 |
self.assertEqual(self.config.GetExclusiveStorage(), bool(value)) |
269 |
|
270 |
for template in constants.DISK_TEMPLATES: |
271 |
if value and template not in constants.DTS_EXCL_STORAGE: |
272 |
self.assertFalse(self.config.IsTemplateSupported(template)) |
273 |
else:
|
274 |
self.assertTrue(self.config.IsTemplateSupported(template)) |
275 |
|
276 |
def testInstanceConversion(self): |
277 |
self.assertTrue(isinstance(self.config["instances"][0], |
278 |
qa_config._QaInstance)) |
279 |
|
280 |
def testAcquireAndReleaseInstance(self): |
281 |
self.assertFalse(compat.any(map(operator.attrgetter("used"), |
282 |
self.config["instances"]))) |
283 |
|
284 |
inst = qa_config.AcquireInstance(_cfg=self.config)
|
285 |
self.assertTrue(inst.used)
|
286 |
self.assertTrue(inst.disk_template is None) |
287 |
|
288 |
qa_config.ReleaseInstance(inst) |
289 |
|
290 |
self.assertFalse(inst.used)
|
291 |
self.assertTrue(inst.disk_template is None) |
292 |
|
293 |
self.assertFalse(compat.any(map(operator.attrgetter("used"), |
294 |
self.config["instances"]))) |
295 |
|
296 |
def testAcquireInstanceTooMany(self): |
297 |
# Acquire all instances
|
298 |
for _ in range(len(self.config["instances"])): |
299 |
inst = qa_config.AcquireInstance(_cfg=self.config)
|
300 |
self.assertTrue(inst.used)
|
301 |
self.assertTrue(inst.disk_template is None) |
302 |
|
303 |
# The next acquisition must fail
|
304 |
self.assertRaises(qa_error.OutOfInstancesError,
|
305 |
qa_config.AcquireInstance, _cfg=self.config)
|
306 |
|
307 |
|
308 |
if __name__ == "__main__": |
309 |
testutils.GanetiTestProgram() |