Coverage for tests/test_Dictionary_1.py : 7%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#!/usr/bin/env python
2#
3# LSST Data Management System
4# Copyright 2008, 2009, 2010 LSST Corporation.
5#
6# This product includes software developed by the
7# LSST Project (http://www.lsst.org/).
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the LSST License Statement and
20# the GNU General Public License along with this program. If not,
21# see <http://www.lsstcorp.org/LegalNotices/>.
22#
23import os
24import unittest
26import lsst.utils.tests
28from lsst.pex.policy import Policy, Dictionary, PolicyFile, DefaultPolicyFile
29from lsst.pex.policy import ValidationError, DictionaryError
30import lsst.pex.exceptions
33class DictionaryTestCase(unittest.TestCase):
34 testDictDir = None
36 def assertRaiseLCE(self, excClass, excMsg, callableObj, failMsg, *args, **kwargs):
37 """
38 Expect callableObj(args, kwargs) to raise an exception of type excClass,
39 and carres a message that contains excMsg.
41 excClass: the subclass of LsstCppException we expect to see
42 excMsg: a substring of the message it should carry
43 callableObj: the thing that, when called, should raise an exception
44 failMsg: the assertion message if this fails
45 args, kwargs (optional): arguments to pass to callableObj
46 """
47 try:
48 callableObj(*args, **kwargs)
49 except excClass as e:
50 self.assertGreater(str(e).find(excMsg), 0,
51 failMsg + ": expected to see the message \"" + excMsg +
52 "\"; actual message was \"" + str(e) + "\".")
53 else:
54 self.fail(failMsg + ": did not raise " + excClass)
56 def assertValidationError(self, errorCode, callableObj, field, value):
57 try:
58 callableObj(field, value)
59 except ValidationError as e:
60 self.assertEqual(e.getErrors(field), errorCode)
62 def getTestDictionary(self, filename=None):
63 if not self.testDictDir:
64 pexPolicyDir = lsst.utils.getPackageDir('pex_policy')
65 self.testDictDir = os.path.join(pexPolicyDir, "tests", "dictionary")
66 return os.path.join(self.testDictDir, filename) if filename else self.testDictDir
68 def testDictionaryLoad(self):
69 d = Dictionary()
70 df = PolicyFile(self.getTestDictionary("simple_dictionary.paf"))
71 self.assertFalse(d.isDictionary(), "false positive dictionary")
72 df.load(d)
73 self.assertTrue(d.isDictionary(), "failed to recognize a dictionary")
75 def testBadDictionary(self):
76 d = Dictionary(self.getTestDictionary("dictionary_bad_policyfile.paf"))
77 self.assertRaiseLCE(DictionaryError, "Illegal type: \"PolicyFile\"",
78 d.makeDef("file_type").getType,
79 "Dictionary specified PolicyFile type")
81 d = Dictionary(self.getTestDictionary("dictionary_bad_unknown_type.paf"))
82 self.assertRaiseLCE(DictionaryError, "Unknown type: \"NotAType\"",
83 d.makeDef("something").getType,
84 "Dictionary specifies unknown types")
86 d = Dictionary(self.getTestDictionary("dictionary_bad_type_type.paf"))
87 self.assertRaiseLCE(DictionaryError, "Expected string",
88 d.makeDef("something").getType,
89 "Expected string \"type\" type")
91 self.assertRaiseLCE(DictionaryError, "property found at bad: min_occurs",
92 Dictionary,
93 "Dictionary has mispelled keyword \"min_occurs\".",
94 self.getTestDictionary("dictionary_bad_keyword.paf"))
96 dbmd = self.getTestDictionary("dictionary_bad_multiple_definitions.paf")
97 self.assertRaiseLCE(DictionaryError, "expected a single",
98 Dictionary,
99 "Dictionary has two 'definitions' sections",
100 dbmd)
102 p = Policy(self.getTestDictionary("values_policy_good_1.paf"))
103 d = Dictionary(self.getTestDictionary("dictionary_bad_multiple_min.paf"))
104 self.assertRaiseLCE(DictionaryError, "Min value for int_ra", d.validate,
105 "Two mins specified.", p)
106 d = Dictionary(self.getTestDictionary("dictionary_bad_multiple_max.paf"))
107 self.assertRaiseLCE(DictionaryError, "Max value for int_ra", d.validate,
108 "Two maxes specified.", p)
109 d = Dictionary(self.getTestDictionary("dictionary_bad_min_wrong_type.paf"))
110 self.assertRaiseLCE(DictionaryError,
111 "Wrong type for int_range_count_type min",
112 d.validate, "Wrong min type.", p)
113 d = Dictionary(self.getTestDictionary("dictionary_bad_max_wrong_type.paf"))
114 self.assertRaiseLCE(DictionaryError,
115 "Wrong type for int_range_count_type max",
116 d.validate, "Wrong max type.", p)
118 # conflict between minOccurs and maxOccurs
119 d = Dictionary(self.getTestDictionary("conflict_occurs_dictionary.paf"))
120 p = Policy(self.getTestDictionary("conflict_occurs_policy_1.paf"))
121 ve = ValidationError("Dictionary_1.py", 1, "testBadDictionary")
122 d.validate(p, ve.cpp)
123 self.assertEqual(ve.getErrors("1to0"), ValidationError.TOO_MANY_VALUES)
124 self.assertEqual(ve.getErrors("2to1"), ValidationError.NOT_AN_ARRAY)
125 self.assertEqual(ve.getParamCount(), 2)
126 p = Policy(self.getTestDictionary("conflict_occurs_policy_2.paf"))
127 ve = ValidationError("Dictionary_1.py", 1, "testBadDictionary")
128 d.validate(p, ve.cpp)
129 self.assertEqual(ve.getErrors("1to0"), ValidationError.MISSING_REQUIRED)
130 self.assertEqual(ve.getErrors("2to1"), ValidationError.TOO_MANY_VALUES)
131 self.assertEqual(ve.getParamCount(), 2)
133 def testSimpleValidate(self):
134 d = Dictionary(self.getTestDictionary("simple_dictionary.paf"))
135 p = Policy(self.getTestDictionary("simple_policy.paf"))
136 ve = ValidationError("Dictionary_1.py", 0, "testSimpleValidate")
137 d.validate(p, ve.cpp)
138 self.assertEqual(ve.getErrors("name"), 0, "no errors in name")
139 self.assertEqual(ve.getErrors("height"), 0, "no errors in height")
140 self.assertEqual(ve.getErrors(), 0, "no errors overall")
142 def testTypeValidation(self):
143 d = Dictionary(self.getTestDictionary("types_dictionary.paf"))
144 self.assertEqual(d.makeDef("undef_type").getType(), Policy.UNDEF,
145 "UNDEF definition type")
146 self.assertEqual(d.makeDef("bool_type").getType(), Policy.BOOL,
147 "BOOL definition type")
148 self.assertEqual(d.makeDef("int_type").getType(), Policy.INT,
149 "INT definition type")
150 self.assertEqual(d.makeDef("double_type").getType(), Policy.DOUBLE,
151 "DOUBLE definition type")
152 self.assertEqual(d.makeDef("string_type").getType(), Policy.STRING,
153 "STRING definition type")
154 self.assertEqual(d.makeDef("policy_type").getType(), Policy.POLICY,
155 "POLICY definition type")
156 self.assertEqual(d.makeDef("file_type").getType(), Policy.POLICY,
157 "POLICY definition type (substituted for PolicyFile)")
159 p = Policy(self.getTestDictionary("types_policy_good.paf"))
161 ve = ValidationError("Dictionary_1.py", 0, "testTypeValidation")
162 d.validate(p, ve.cpp)
163 self.assertEqual(ve.getErrors("file_type"), ValidationError.NOT_LOADED,
164 "require loadPolicyFiles before validating")
165 self.assertEqual(ve.getErrors("undef_file"), ValidationError.NOT_LOADED,
166 "require loadPolicyFiles before validating")
167 self.assertEqual(ve.getErrors(), ValidationError.NOT_LOADED, "no other errors")
168 self.assertEqual(ve.getParamCount(), 2, "no other errors")
170 p.loadPolicyFiles(self.getTestDictionary(), True)
171 ve = ValidationError("Dictionary_1.py", 0, "testTypeValidation")
172 d.validate(p, ve.cpp)
174 self.assertEqual(ve.getErrors("undef_type"), 0, "no errors with undef")
175 self.assertEqual(ve.getErrors("int_type"), 0, "no errors with int")
176 self.assertEqual(ve.getErrors("double_type"), 0, "no errors with double")
177 self.assertEqual(ve.getErrors("bool_type"), 0, "no errors with bool")
178 self.assertEqual(ve.getErrors("string_type"), 0, "no errors with string")
179 self.assertEqual(ve.getErrors("policy_type"), 0, "no errors with policy")
180 self.assertEqual(ve.getErrors("file_type"), 0, "no errors with file")
181 self.assertEqual(ve.getErrors(), 0, "no errors overall")
183 def testWrongType(self):
184 d = Dictionary(self.getTestDictionary("types_dictionary.paf"))
186 p = Policy(self.getTestDictionary("types_policy_bad_bool.paf"))
187 ve = ValidationError("Dictionary_1.py", 0, "testWrongType")
188 d.validate(p, ve.cpp)
189 self.assertEqual(ve.getErrors(), ValidationError.WRONG_TYPE, "wrong type")
190 self.assertEqual(ve.getParamCount(), 5, "number of errors")
191 self.assertEqual(ve.getErrors("bool_type"), 0, "correct type")
193 p = Policy(self.getTestDictionary("types_policy_bad_int.paf"))
194 ve = ValidationError("Dictionary_1.py", 1, "testWrongType")
195 d.validate(p, ve.cpp)
196 self.assertEqual(ve.getErrors(), ValidationError.WRONG_TYPE, "wrong type")
197 self.assertEqual(ve.getParamCount(), 5, "number of errors")
198 self.assertEqual(ve.getErrors("int_type"), 0, "correct type")
199 self.assertEqual(ve.getErrors("double_type"), ValidationError.WRONG_TYPE,
200 "int can't pass as double")
202 p = Policy(self.getTestDictionary("types_policy_bad_double.paf"))
203 ve = ValidationError("Dictionary_1.py", 2, "testWrongType")
204 d.validate(p, ve.cpp)
205 self.assertEqual(ve.getErrors(), ValidationError.WRONG_TYPE, "wrong type")
206 self.assertEqual(ve.getParamCount(), 5, "number of errors")
207 self.assertEqual(ve.getErrors("double_type"), 0, "correct type")
209 p = Policy(self.getTestDictionary("types_policy_bad_string.paf"))
210 ve = ValidationError("Dictionary_1.py", 3, "testWrongType")
211 d.validate(p, ve.cpp)
212 self.assertEqual(ve.getErrors(), ValidationError.WRONG_TYPE, "wrong type")
213 self.assertEqual(ve.getParamCount(), 5, "number of errors")
214 self.assertEqual(ve.getErrors("string_type"), 0, "correct type")
216 p = Policy(self.getTestDictionary("types_policy_bad_policy.paf"))
217 ve = ValidationError("Dictionary_1.py", 4, "testWrongType")
218 d.validate(p, ve.cpp)
219 self.assertEqual(ve.getErrors(), ValidationError.WRONG_TYPE, "wrong type")
220 self.assertEqual(ve.getParamCount(), 4, "number of errors")
221 self.assertEqual(ve.getErrors("policy_type"), 0, "correct type")
222 self.assertEqual(ve.getErrors("file_type"), 0, "correct type")
224 p = Policy(self.getTestDictionary("types_policy_bad_file.paf"))
225 ve = ValidationError("Dictionary_1.py", 5, "testWrongType")
226 d.validate(p, ve.cpp)
227 self.assertEqual(ve.getErrors(), ValidationError.NOT_LOADED, "not loaded")
228 self.assertEqual(ve.getParamCount(), 6, "number of errors")
229 self.assertEqual(ve.getErrors("bool_type"), ValidationError.NOT_LOADED,
230 "not loaded")
231 self.assertEqual(ve.getErrors("file_type"), ValidationError.NOT_LOADED,
232 "not loaded")
233 self.assertEqual(ve.getErrors("policy_type"), ValidationError.NOT_LOADED,
234 "not loaded")
235 p.loadPolicyFiles(self.getTestDictionary(), True)
236 ve = ValidationError("Dictionary_1.py", 6, "testWrongType")
237 d.validate(p, ve.cpp)
238 self.assertEqual(ve.getErrors(), ValidationError.WRONG_TYPE, "wrong type")
239 self.assertEqual(ve.getErrors("file_type"), 0, "correct type")
240 self.assertEqual(ve.getErrors("policy_type"), 0, "correct type")
241 self.assertEqual(ve.getParamCount(), 4, "wrong type")
243 def testValues(self):
244 d = Dictionary(self.getTestDictionary("values_dictionary.paf"))
245 d.check()
246 p = Policy(self.getTestDictionary("values_policy_good_1.paf"))
247 ve = ValidationError("Dictionary_1.py", 0, "testValues")
248 d.validate(p, ve.cpp)
249 self.assertEqual(ve.getParamCount(), 0)
251 # policy: disallow allowed, min, max
252 p = Policy(self.getTestDictionary("values_policy_bad_policy_set.paf"))
253 ve = ValidationError("Dictionary_1.py", 1, "testValues")
254 d.validate(p, ve.cpp)
255 self.assertEqual(ve.getErrors("policy_set_type"),
256 ValidationError.VALUE_DISALLOWED)
257 p = Policy(self.getTestDictionary("values_policy_bad_policy_max.paf"))
258 ve = ValidationError("Dictionary_1.py", 2, "testValues")
259 d.validate(p, ve.cpp)
260 self.assertEqual(ve.getErrors("policy_max_type"),
261 ValidationError.VALUE_OUT_OF_RANGE)
262 p = Policy(self.getTestDictionary("values_policy_bad_policy_min.paf"))
263 ve = ValidationError("Dictionary_1.py", 3, "testValues")
264 d.validate(p, ve.cpp)
265 self.assertEqual(ve.getErrors("policy_min_type"),
266 ValidationError.VALUE_OUT_OF_RANGE)
268 # minOccurs/maxOccurs
269 p = Policy(self.getTestDictionary("values_policy_bad_occurs.paf"))
270 ve = ValidationError("Dictionary_1.py", 1, "testValues")
271 d.validate(p, ve.cpp)
272 self.assertEqual(ve.getParamCount(), 6)
273 self.assertEqual(ve.getErrors("bool_set_count_type"),
274 ValidationError.TOO_MANY_VALUES)
275 self.assertEqual(ve.getErrors("int_range_count_type"),
276 ValidationError.MISSING_REQUIRED)
277 self.assertEqual(ve.getErrors("double_range_count_type"),
278 ValidationError.TOO_MANY_VALUES)
279 self.assertEqual(ve.getErrors("string_count_type"),
280 ValidationError.ARRAY_TOO_SHORT)
281 self.assertEqual(ve.getErrors("disallowed"),
282 ValidationError.TOO_MANY_VALUES)
283 self.assertEqual(ve.getErrors("policy_count_type"),
284 ValidationError.TOO_MANY_VALUES)
286 # min
287 p = Policy(self.getTestDictionary("values_policy_bad_min.paf"))
288 ve = ValidationError("Dictionary_1.py", 1, "testValues")
289 d.validate(p, ve.cpp)
290 self.assertEqual(ve.getParamCount(), 4)
291 self.assertEqual(ve.getErrors(), ValidationError.VALUE_OUT_OF_RANGE)
292 self.assertEqual(ve.getErrors("string_count_type"), ValidationError.OK)
293 self.assertEqual(ve.getErrors("policy_count_type"), ValidationError.OK)
294 # max
295 p = Policy(self.getTestDictionary("values_policy_bad_max.paf"))
296 ve = ValidationError("Dictionary_1.py", 1, "testValues")
297 d.validate(p, ve.cpp)
298 self.assertEqual(ve.getParamCount(), 4)
299 self.assertEqual(ve.getErrors(), ValidationError.VALUE_OUT_OF_RANGE)
300 self.assertEqual(ve.getErrors("string_count_type"), ValidationError.OK)
301 self.assertEqual(ve.getErrors("policy_count_type"), ValidationError.OK)
303 # allowed
304 p = Policy(self.getTestDictionary("values_policy_bad_allowed.paf"))
305 ve = ValidationError("Dictionary_1.py", 1, "testValues")
306 d.validate(p, ve.cpp)
307 self.assertEqual(ve.getParamCount(), 4)
308 self.assertEqual(ve.getErrors(), ValidationError.VALUE_DISALLOWED)
309 self.assertEqual(ve.getErrors("int_range_count_type"), ValidationError.OK)
310 self.assertEqual(ve.getErrors("string_count_type"), ValidationError.OK)
311 self.assertEqual(ve.getErrors("policy_count_type"), ValidationError.OK)
313 # allowed & min/max
314 p = Policy(self.getTestDictionary("values_policy_bad_allowedminmax.paf"))
315 ve = ValidationError("Dictionary_1.py", 1, "testValues")
316 d.validate(p, ve.cpp)
317 self.assertEqual(ve.getParamCount(), 2)
318 self.assertEqual(ve.getErrors("int_range_set_type"),
319 int(ValidationError.VALUE_DISALLOWED) +
320 int(ValidationError.VALUE_OUT_OF_RANGE))
321 self.assertEqual(ve.getErrors("double_range_count_type"),
322 int(ValidationError.TOO_MANY_VALUES) +
323 int(ValidationError.VALUE_OUT_OF_RANGE))
324 ve = ValidationError("Dictionary_1.py", 1, "testValues")
325 d.validate(p, ve.cpp)
327 def testNested(self):
328 self.assertRaiseLCE(DictionaryError,
329 "policy_bad_subdef.dictionary is a string",
330 Dictionary, "Malformed subdictionary",
331 self.getTestDictionary("nested_dictionary_bad_1.paf"))
333 p = Policy(self.getTestDictionary("nested_policy_good.paf"))
334 self.assertRaiseLCE(DictionaryError, "Unknown Dictionary property",
335 Dictionary, "Malformed subdictionary",
336 self.getTestDictionary("nested_dictionary_bad_2.paf"))
338 d = Dictionary(self.getTestDictionary("nested_dictionary_good.paf"))
339 d.check()
340 self.assertRaiseLCE(lsst.pex.exceptions.LogicError, "dictionaryFile needs to be loaded",
341 d.validate, "dictionaryFile not loaded", p)
342 self.assertFalse(d.hasSubDictionary("policy_1"))
343 self.assertTrue(d.hasSubDictionary("policy_2"))
344 self.assertFalse(d.hasSubDictionary("policy_load"))
345 n = d.loadPolicyFiles(self.getTestDictionary(), True)
346 self.assertTrue(d.hasSubDictionary("policy_load"))
347 self.assertEqual(n, 1) # number of files loaded
348 d.validate(p)
350 ve = ValidationError("Dictionary_1.py", 1, "testNested")
351 p = Policy(self.getTestDictionary("nested_policy_bad.paf"))
352 d.validate(p, ve.cpp)
353 self.assertEqual(ve.getErrors("policy_1"), ValidationError.WRONG_TYPE)
354 self.assertEqual(ve.getErrors("policy_2.foo"),
355 ValidationError.VALUE_DISALLOWED)
356 self.assertEqual(ve.getErrors("policy_2.bar"),
357 ValidationError.MISSING_REQUIRED)
358 self.assertEqual(ve.getErrors("policy_3.baz.qux"),
359 ValidationError.WRONG_TYPE)
360 self.assertEqual(ve.getErrors("policy_3.baz.paisley"),
361 ValidationError.MISSING_REQUIRED)
362 self.assertEqual(ve.getErrors("policy_3.baz.paisley"),
363 ValidationError.MISSING_REQUIRED)
364 self.assertEqual(ve.getErrors("policy_load.height"),
365 ValidationError.MISSING_REQUIRED)
366 self.assertEqual(ve.getParamCount(), 6)
368 # multiple nesting
369 p = Policy(self.getTestDictionary("nested_policy_1.paf"))
370 n = p.loadPolicyFiles(self.getTestDictionary())
371 self.assertEqual(n, 3)
372 self.assertEqual(p.getString("1.2b.foo"), "bar")
374 d = Dictionary(self.getTestDictionary("nested_dictionary_1.paf"))
375 n = d.loadPolicyFiles(self.getTestDictionary())
376 self.assertEqual(n, 3)
377 p = Policy(True, d) # load from defaults
378 self.assertEqual(p.getString("1.2a.foo"), "bar")
379 self.assertEqual(p.getString("1.2b.foo"), "bar")
381 # error in child
382 d = Dictionary(self.getTestDictionary("nested_dictionary_bad_child.paf"))
383 d.loadPolicyFiles(self.getTestDictionary())
384 # this should really be caught during loadPolicyFiles(), above
385 self.assertRaiseLCE(DictionaryError, "Unknown type: \"NotAType\"",
386 d.makeDef("sub.something").getType,
387 "Loaded sub-dictionary specified a bogus type")
389 def testChildDef(self):
390 # simple
391 d = Dictionary(self.getTestDictionary("childdef_simple_dictionary.paf"))
392 p = Policy(self.getTestDictionary("childdef_simple_policy_good.paf"))
393 d.validate(p)
394 p = Policy(self.getTestDictionary("childdef_simple_policy_bad.paf"))
395 ve = ValidationError("Dictionary_1.py", 1, "testChildDef")
396 d.validate(p, ve.cpp)
397 self.assertEqual(ve.getErrors("baz"), ValidationError.WRONG_TYPE)
399 # multiple childDefs (DictionaryError)
400 d = Dictionary(self.getTestDictionary("childdef_dictionary_bad_multiple.paf"))
401 self.assertRaiseLCE(DictionaryError, "Multiple childDef",
402 d.validate, "Dictionary specifies unknown types", p)
404 # complex
405 d = Dictionary(self.getTestDictionary("childdef_complex_dictionary.paf"))
406 p = Policy(self.getTestDictionary("childdef_complex_policy_good_1.paf"))
407 d.validate(p)
408 p = Policy(self.getTestDictionary("childdef_complex_policy_good_2.paf"))
409 d.validate(p)
410 p = Policy(self.getTestDictionary("childdef_complex_policy_bad_1.paf"))
411 ve = ValidationError("Dictionary_1.py", 1, "testChildDef")
412 d.validate(p, ve.cpp)
413 self.assertEqual(ve.getErrors("joe"), ValidationError.NOT_AN_ARRAY)
414 self.assertEqual(ve.getErrors("deb"), ValidationError.NOT_AN_ARRAY)
415 self.assertEqual(ve.getErrors("bob"), ValidationError.NOT_AN_ARRAY)
416 self.assertEqual(ve.getErrors("bob.bar"), ValidationError.NOT_AN_ARRAY)
417 self.assertEqual(ve.getErrors("nested.helen.qux"),
418 ValidationError.MISSING_REQUIRED)
419 self.assertEqual(ve.getErrors("nested.marvin.rafael"),
420 ValidationError.TOO_MANY_VALUES)
421 self.assertEqual(ve.getErrors("disallowed.foo"),
422 ValidationError.TOO_MANY_VALUES)
423 self.assertEqual(ve.getParamCount(), 7)
425 def testDefaults(self):
426 p = Policy.createPolicy(self.getTestDictionary("defaults_dictionary_good.paf"),
427 "", True)
428 self.assertEqual(p.valueCount("bool_set_count"), 1)
429 self.assertIs(p.getBool("bool_set_count"), True)
430 self.assertEqual(p.valueCount("int_range_count"), 3)
431 self.assertEqual(p.getDouble("deep.sub_double"), 1.)
432 self.assertEqual(p.get("indirect4.string_type"), "foo")
434 try:
435 p = Policy.createPolicy(self.getTestDictionary("defaults_dictionary_bad_1.paf"),
436 "", True)
437 except ValidationError as ve:
438 self.assertEqual(ve.getErrors("double"),
439 ValidationError.WRONG_TYPE)
440 self.assertEqual(ve.getErrors("int_range_count"),
441 ValidationError.NOT_AN_ARRAY)
442 self.assertEqual(ve.getErrors("bool_set_count"),
443 ValidationError.TOO_MANY_VALUES)
444 self.assertEqual(ve.getErrors("deep.sub_double"),
445 ValidationError.WRONG_TYPE)
446 self.assertEqual(ve.getParamCount(), 4)
448 # test setting and adding when created with a dictionary
449 def testSetAdd(self):
450 p = Policy.createPolicy(self.getTestDictionary("defaults_dictionary_good.paf"),
451 "", True)
452 self.assertTrue(p.canValidate())
453 self.assertValidationError(ValidationError.TOO_MANY_VALUES,
454 p.add, "bool_set_count", True)
455 self.assertEqual(p.valueCount("bool_set_count"), 1)
456 self.assertValidationError(ValidationError.VALUE_DISALLOWED,
457 p.set, "bool_set_count", False)
458 self.assertIs(p.getBool("bool_set_count"), True)
459 p.set("int_range_count", -7)
460 self.assertValidationError(ValidationError.VALUE_OUT_OF_RANGE,
461 p.add, "int_range_count", 10)
462 # add & set don't check against minOccurs, but validate() does
463 try:
464 p.validate()
465 except ValidationError as ve:
466 self.assertEqual(ve.getErrors("int_range_count"),
467 ValidationError.NOT_AN_ARRAY)
468 self.assertEqual(ve.getErrors("required"),
469 ValidationError.MISSING_REQUIRED)
470 p.add("int_range_count", -8)
471 p.set("required", "foo")
472 p.validate()
474 def testSelfValidation(self):
475 # assign a dictionary after creation
476 p = Policy(self.getTestDictionary("types_policy_good.paf"))
477 p.loadPolicyFiles(self.getTestDictionary(), True)
478 typesDict = Dictionary(self.getTestDictionary("types_dictionary.paf"))
479 valuesDict = Dictionary(self.getTestDictionary("values_dictionary.paf"))
480 self.assertFalse(p.canValidate())
481 p.setDictionary(typesDict)
482 self.assertTrue(p.canValidate())
483 p.validate()
484 p.set("bool_type", True)
485 self.assertValidationError(
486 ValidationError.WRONG_TYPE, p.set, "bool_type", "foo")
488 # create with dictionary
489 p = Policy.createPolicy(self.getTestDictionary("types_dictionary.paf"), "", True)
490 self.assertTrue(p.canValidate())
491 p.set("bool_type", True)
492 self.assertValidationError(
493 ValidationError.WRONG_TYPE, p.set, "bool_type", "foo")
495 # assign a dictionary after invalid modifications
496 p = Policy()
497 p.set("bool_type", "foo")
498 p.setDictionary(typesDict)
499 ve = ValidationError("Dictionary_1.py", 1, "testSelfValidation")
500 p.validate(ve.cpp)
501 self.assertEqual(ve.getErrors("bool_type"), ValidationError.WRONG_TYPE)
502 try:
503 p.validate()
504 except ValidationError as ve:
505 self.assertEqual(ve.getErrors("bool_type"), ValidationError.WRONG_TYPE)
506 self.assertEqual(ve.getParamCount(), 1)
507 p.set("bool_type", True)
508 p.set("int_type", 1)
509 p.validate()
511 # switch dictionaries
512 oldD = p.getDictionary()
513 p.setDictionary(valuesDict)
514 try:
515 p.validate()
516 except ValidationError as ve:
517 self.assertEqual(ve.getErrors("bool_type"),
518 ValidationError.UNKNOWN_NAME)
519 p.set("string_range_type", "moo")
520 try:
521 p.set("string_range_type", "victor")
522 except ValidationError as ve:
523 self.assertEqual(ve.getErrors("string_range_type"),
524 ValidationError.VALUE_OUT_OF_RANGE)
525 p.setDictionary(oldD)
526 p.remove("string_range_type")
527 p.validate()
529 def testMergeDefaults(self):
530 # from a non-trivial dictionary
531 p = Policy(self.getTestDictionary("defaults_policy_partial.paf"))
532 p.set("required", "foo")
533 d = Dictionary(self.getTestDictionary("defaults_dictionary_good.paf"))
534 d.loadPolicyFiles(self.getTestDictionary(), True)
535 self.assertEqual(p.nameCount(), 2)
536 p.mergeDefaults(d)
537 self.assertEqual(p.valueCount("int_range_count"), 3)
538 self.assertEqual(p.nameCount(), 7)
540 # from a policy that's really a dictionary
541 p = Policy()
542 pd = Policy(self.getTestDictionary("defaults_dictionary_indirect.paf"))
543 p.mergeDefaults(pd)
544 self.assertEqual(p.getString("string_type"), "foo")
545 self.assertTrue(p.getDictionary().isDictionary())
547 # from a policy that's really a non-trivial dictionary
548 p = Policy(self.getTestDictionary("defaults_policy_partial.paf"))
549 p.set("required", "foo")
550 pd = Policy(self.getTestDictionary("defaults_dictionary_policy.paf"))
551 pd.loadPolicyFiles(self.getTestDictionary(), True)
552 self.assertEqual(p.nameCount(), 2)
553 p.mergeDefaults(pd)
554 self.assertEqual(p.valueCount("int_range_count"), 3)
555 self.assertEqual(p.nameCount(), 5)
557 # ensure post-load validation
558 p.set("int_range_count", -5)
559 self.assertValidationError(ValidationError.UNKNOWN_NAME,
560 p.add, "unknown", 0)
562 # test throwing validation
563 p = Policy(self.getTestDictionary("defaults_policy_partial.paf"))
564 try:
565 p.mergeDefaults(pd)
566 except ValidationError as ve:
567 self.assertEqual(ve.getErrors("required"),
568 ValidationError.MISSING_REQUIRED)
570 # non-throwing validation
571 p = Policy(self.getTestDictionary("defaults_policy_partial.paf"))
572 ve = ValidationError("Dictionary_1.py", 1, "testMergeDefaults")
573 p.mergeDefaults(pd, False, ve.cpp)
574 self.assertEqual(ve.getErrors("required"), ValidationError.MISSING_REQUIRED)
575 self.assertEqual(ve.getParamCount(), 1)
577 # non-retention
578 p = Policy(self.getTestDictionary("defaults_policy_partial.paf"))
579 p.set("required", "foo")
580 p.mergeDefaults(pd, False)
581 # make sure validate() fails gracefully when no dictionary present
582 self.assertRaiseLCE(DictionaryError, "No dictionary",
583 p.validate, "No dictionary assigned")
584 p.add("unknown", 0) # would be rejected if dictionary was kept
586 # deep merge from a Policy that's not a Dictionary
587 p = Policy(self.getTestDictionary("defaults_policy_partial.paf"))
588 p.mergeDefaults(Policy(self.getTestDictionary("defaults_policy_most.paf")))
589 self.assertEqual(p.nameCount(), 3)
590 self.assertIs(p.getBool("bool_set_count"), True)
591 self.assertEqual(p.getString("indirect.string_type"), "bar")
593 # propagation of a Dictionary from one Policy to another via mergeDefaults
594 d = Dictionary(self.getTestDictionary("defaults_dictionary_complete.paf"))
595 d.loadPolicyFiles(self.getTestDictionary())
596 pEmpty = Policy()
597 pEmpty.mergeDefaults(d)
598 self.assertTrue(pEmpty.canValidate())
599 pPartial = Policy(self.getTestDictionary("defaults_policy_partial.paf"))
600 pPartial.mergeDefaults(pEmpty)
601 self.assertTrue(pPartial.canValidate(), "Dictionary handed off via mergeDefaults.")
603 # test the sample code at http://dev.lsstcorp.org/trac/wiki/PolicyHowto
604 def testSampleCode(self):
605 policyFile = DefaultPolicyFile("pex_policy", "defaults_dictionary_complete.paf",
606 "tests/dictionary")
607 defaults = Policy.createPolicy(policyFile, policyFile.getRepositoryPath(), True)
608 policy = Policy()
609 policy.mergeDefaults(defaults)
610 self.assertTrue(policy.canValidate())
612 policy = Policy()
613 policy.mergeDefaults(defaults, False)
614 self.assertFalse(policy.canValidate())
616 # even if not keeping it around for future validation, validate the merge now
617 policy = Policy()
618 policy.set("bad", "worse")
619 self.assertValidationError(ValidationError.UNKNOWN_NAME,
620 policy.mergeDefaults, defaults, False)
621 self.assertFalse(policy.canValidate())
623 # test operations on an empty sub-dictionary (ticket 1210)
624 def testEmptySubdict(self):
625 d = Dictionary(self.getTestDictionary("empty_subdictionary.paf"))
626 p = Policy()
627 p.set("empty_required", Policy(self.getTestDictionary("simple_policy.paf")))
628 p.mergeDefaults(d)
629 self.assertEqual(p.get("empty_sub_with_default.foo"), "bar")
630 p.setDictionary(d)
631 # this works because there is a definition for "empty_sub_with_default.foo"
632 p.set("empty_sub_with_default.foo", "baz")
634 p2 = Policy()
635 p2.set("foo", "baz")
636 p.set("empty_sub_no_default", p2)
637 # this fails because Policy tries to makeDef("empty_sub_no_default.foo")
638 # which fails because there's only a definition for "empty_sub_no_default",
639 # but it doesn't contain any sub-definitions
640 # p.set("empty_sub_no_default.foo", "baz")
641 self.assertRaiseLCE(DictionaryError,
642 "empty_sub_no_default.dictionary not found",
643 p.set, "Empty policy definition -- if this fails, "
644 "it means a known bug has been fixed. That's good.",
645 "empty_sub_no_default.foo", "baz")
648class TestMemory(lsst.utils.tests.MemoryTestCase):
649 pass
652def setup_module(module):
653 lsst.utils.tests.init()
656if __name__ == "__main__": 656 ↛ 657line 656 didn't jump to line 657, because the condition on line 656 was never true
657 lsst.utils.tests.init()
658 unittest.main()