Hide keyboard shortcuts

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 

25 

26import lsst.utils.tests 

27 

28from lsst.pex.policy import Policy, Dictionary, PolicyFile, DefaultPolicyFile 

29from lsst.pex.policy import ValidationError, DictionaryError 

30import lsst.pex.exceptions 

31 

32 

33class DictionaryTestCase(unittest.TestCase): 

34 testDictDir = None 

35 

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. 

40 

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) 

55 

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) 

61 

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 

67 

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") 

74 

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") 

80 

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") 

85 

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") 

90 

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")) 

95 

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) 

101 

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) 

117 

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) 

132 

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") 

141 

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)") 

158 

159 p = Policy(self.getTestDictionary("types_policy_good.paf")) 

160 

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") 

169 

170 p.loadPolicyFiles(self.getTestDictionary(), True) 

171 ve = ValidationError("Dictionary_1.py", 0, "testTypeValidation") 

172 d.validate(p, ve.cpp) 

173 

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") 

182 

183 def testWrongType(self): 

184 d = Dictionary(self.getTestDictionary("types_dictionary.paf")) 

185 

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") 

192 

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") 

201 

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") 

208 

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") 

215 

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") 

223 

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") 

242 

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) 

250 

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) 

267 

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) 

285 

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) 

302 

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) 

312 

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) 

326 

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")) 

332 

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")) 

337 

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) 

349 

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) 

367 

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") 

373 

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") 

380 

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") 

388 

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) 

398 

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) 

403 

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) 

424 

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") 

433 

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) 

447 

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() 

473 

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") 

487 

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") 

494 

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() 

510 

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() 

528 

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) 

539 

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()) 

546 

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) 

556 

557 # ensure post-load validation 

558 p.set("int_range_count", -5) 

559 self.assertValidationError(ValidationError.UNKNOWN_NAME, 

560 p.add, "unknown", 0) 

561 

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) 

569 

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) 

576 

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 

585 

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") 

592 

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.") 

602 

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()) 

611 

612 policy = Policy() 

613 policy.mergeDefaults(defaults, False) 

614 self.assertFalse(policy.canValidate()) 

615 

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()) 

622 

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") 

633 

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") 

646 

647 

648class TestMemory(lsst.utils.tests.MemoryTestCase): 

649 pass 

650 

651 

652def setup_module(module): 

653 lsst.utils.tests.init() 

654 

655 

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()