1# Copyright 2017 CodiLime 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15from __future__ import unicode_literals 16 17import unittest 18import six 19 20from veles.data.bindata import BinData 21from veles.schema.nodeid import NodeID 22from veles.schema import fields, enumeration 23from veles.proto.exceptions import VelesException, SchemaError 24 25 26class Piwo(object): 27 def dump(self): 28 return 'piwo' 29 30 @classmethod 31 def load(cls, value): 32 if value != 'piwo': 33 raise SchemaError 34 return Piwo() 35 36 def __eq__(self, other): 37 return type(self) == type(other) 38 39 def __ne__(self, other): 40 return not self.__eq__(other) 41 42 def __hash__(self): 43 return 13 44 45 46class Zlew(object): 47 def dump(self): 48 return 'zlew' 49 50 @classmethod 51 def load(cls, value): 52 if value != 'zlew': 53 raise SchemaError 54 return Zlew() 55 56 def __eq__(self, other): 57 return type(self) == type(other) 58 59 def __ne__(self, other): 60 return not self.__eq__(other) 61 62 def __hash__(self): 63 return 13 64 65 66class ZlewType(enumeration.EnumModel): 67 ZLEW = 'zlewzlewzlew' 68 TURBOZLEW = b'turbo' 69 DWUZLEW = 2 70 71 72class TestFields(unittest.TestCase): 73 def test_field(self): 74 a = fields.Any(default='zlew') 75 a.__set_name__(None, 'a') 76 self.assertEqual(a.name, 'a') 77 a.validate(1234) 78 a.validate({}) 79 with self.assertRaises(SchemaError): 80 a.validate(None) 81 tv = { 82 'a': 123, 83 'b': 'c', 84 } 85 self.assertEqual(a.dump(tv), tv) 86 self.assertEqual(a.load(tv), tv) 87 with self.assertRaises(SchemaError): 88 a.load(None) 89 90 with self.assertRaises(TypeError): 91 fields.Any(optional='zlew') 92 with self.assertRaises(ValueError): 93 a = fields.Any(optional=True, default='zlew') 94 95 def test_empty(self): 96 with self.assertRaises(TypeError): 97 fields.Empty(default='zlew') 98 with self.assertRaises(TypeError): 99 fields.Empty(optional=False) 100 101 a = fields.Empty() 102 a.validate(None) 103 self.assertEqual(a.dump(None), None) 104 self.assertEqual(a.load(None), None) 105 with self.assertRaises(SchemaError): 106 a.validate(1) 107 with self.assertRaises(SchemaError): 108 a.load(1) 109 110 def test_boolean(self): 111 with self.assertRaises(SchemaError): 112 fields.Boolean(default='zlew') 113 114 a = fields.Boolean(optional=True) 115 a.validate(True) 116 a.validate(False) 117 a.validate(None) 118 with self.assertRaises(SchemaError): 119 a.validate(1) 120 self.assertEqual(a.dump(None), None) 121 self.assertEqual(a.dump(True), True) 122 self.assertEqual(a.dump(False), False) 123 self.assertEqual(a.load(None), None) 124 self.assertEqual(a.load(True), True) 125 self.assertEqual(a.load(False), False) 126 with self.assertRaises(SchemaError): 127 a.load(1) 128 129 def test_float(self): 130 a = fields.Float() 131 a.validate(1.234) 132 with self.assertRaises(SchemaError): 133 a.validate(1) 134 with self.assertRaises(SchemaError): 135 a.validate('1.0') 136 self.assertEqual(a.dump(1.234), 1.234) 137 self.assertEqual(a.load(1.234), 1.234) 138 with self.assertRaises(SchemaError): 139 a.load(1) 140 with self.assertRaises(SchemaError): 141 a.load('1.0') 142 143 def test_string(self): 144 a = fields.String() 145 a.validate('abcd') 146 with self.assertRaises(SchemaError): 147 a.validate(b'abcd') 148 with self.assertRaises(SchemaError): 149 a.validate(1234) 150 self.assertEqual(a.dump('abcd'), 'abcd') 151 self.assertEqual(a.load('abcd'), 'abcd') 152 with self.assertRaises(SchemaError): 153 a.load(b'abcd') 154 with self.assertRaises(SchemaError): 155 a.load(1234) 156 157 def test_binary(self): 158 a = fields.Binary() 159 a.validate(b'abcd') 160 with self.assertRaises(SchemaError): 161 a.validate('abcd') 162 with self.assertRaises(SchemaError): 163 a.validate(1234) 164 self.assertEqual(a.dump(b'abcd'), b'abcd') 165 self.assertEqual(a.load(b'abcd'), b'abcd') 166 with self.assertRaises(SchemaError): 167 a.load('abcd') 168 with self.assertRaises(SchemaError): 169 a.load(1234) 170 171 def test_nodeid(self): 172 a = fields.NodeID() 173 id = NodeID() 174 a.validate(id) 175 with self.assertRaises(SchemaError): 176 a.validate(b'abcd') 177 with self.assertRaises(SchemaError): 178 a.validate(1234) 179 self.assertEqual(a.dump(id), id) 180 self.assertEqual(a.load(id), id) 181 with self.assertRaises(SchemaError): 182 a.load(b'abcd') 183 with self.assertRaises(SchemaError): 184 a.load(1234) 185 186 def test_bindata(self): 187 a = fields.BinData() 188 data = BinData(8, [0x12, 0x34]) 189 a.validate(data) 190 with self.assertRaises(SchemaError): 191 a.validate(b'abcd') 192 with self.assertRaises(SchemaError): 193 a.validate(1234) 194 self.assertEqual(a.dump(data), data) 195 self.assertEqual(a.load(data), data) 196 with self.assertRaises(SchemaError): 197 a.load(b'abcd') 198 with self.assertRaises(SchemaError): 199 a.load(1234) 200 201 def test_integer(self): 202 a = fields.Integer() 203 a.validate(0) 204 a.validate(1) 205 a.validate(-1) 206 a.validate(0x123456789abcdef123456789abcdef) 207 a.validate(-0x123456789abcdef123456789abcdef) 208 with self.assertRaises(SchemaError): 209 a.validate(False) 210 with self.assertRaises(SchemaError): 211 a.validate(True) 212 213 a = fields.Integer(minimum=-123, maximum=456) 214 a.validate(-123) 215 a.validate(123) 216 a.validate(234) 217 a.validate(456) 218 with self.assertRaises(SchemaError): 219 a.validate(-0x123456789abcdef123456789abcdef) 220 with self.assertRaises(SchemaError): 221 a.validate(-124) 222 with self.assertRaises(SchemaError): 223 a.validate(457) 224 with self.assertRaises(SchemaError): 225 a.validate(0x123456789abcdef123456789abcdef) 226 227 a = fields.Integer(minimum=123) 228 a.validate(123) 229 a.validate(234) 230 a.validate(456) 231 a.validate(0x123456789abcdef123456789abcdef) 232 with self.assertRaises(SchemaError): 233 a.validate(0) 234 with self.assertRaises(SchemaError): 235 a.validate(-123) 236 with self.assertRaises(SchemaError): 237 a.validate(122) 238 239 with self.assertRaises(TypeError): 240 fields.Integer(minimum='zlew') 241 with self.assertRaises(TypeError): 242 fields.Integer(maximum='zlew') 243 fields.Integer(minimum=3, maximum=3) 244 fields.Integer(minimum=3) 245 fields.Integer(maximum=3) 246 with self.assertRaises(ValueError): 247 fields.Integer(minimum=3, maximum=2) 248 249 def test_unsigned_integer(self): 250 a = fields.UnsignedInteger() 251 a.validate(0) 252 a.validate(1) 253 a.validate(123) 254 a.validate(0x123456789abcdef123456789abcdef) 255 with self.assertRaises(SchemaError): 256 a.validate(-122) 257 with self.assertRaises(SchemaError): 258 a.validate(-1) 259 with self.assertRaises(SchemaError): 260 a.validate(-0x123456789abcdef123456789abcdef) 261 262 with self.assertRaises(ValueError): 263 fields.UnsignedInteger(minimum=-1) 264 with self.assertRaises(TypeError): 265 fields.UnsignedInteger(minimum=None) 266 with self.assertRaises(ValueError): 267 fields.UnsignedInteger(maximum=-1) 268 fields.UnsignedInteger(maximum=0) 269 fields.UnsignedInteger(minimum=123) 270 fields.UnsignedInteger(maximum=123) 271 fields.UnsignedInteger(maximum=None) 272 273 def test_small_integer(self): 274 a = fields.SmallInteger() 275 a.validate(0) 276 a.validate(-1) 277 a.validate(1) 278 a.validate(-0x8000000000000000) 279 a.validate(0x7fffffffffffffff) 280 with self.assertRaises(SchemaError): 281 a.validate(-0x8000000000000001) 282 with self.assertRaises(SchemaError): 283 a.validate(0x8000000000000000) 284 fields.SmallInteger(minimum=-1) 285 fields.SmallInteger(maximum=-1) 286 fields.SmallInteger(maximum=0x7fffffffffffffff) 287 fields.SmallInteger(minimum=-0x8000000000000000) 288 with self.assertRaises(ValueError): 289 fields.SmallInteger(maximum=0x8000000000000000) 290 with self.assertRaises(ValueError): 291 fields.SmallInteger(minimum=-0x8000000000000001) 292 with self.assertRaises(TypeError): 293 fields.SmallInteger(maximum=None) 294 with self.assertRaises(TypeError): 295 fields.SmallInteger(minimum=None) 296 297 def test_small_unsigned_integer(self): 298 a = fields.SmallUnsignedInteger() 299 a.validate(0) 300 a.validate(1) 301 a.validate(0xffffffffffffffff) 302 with self.assertRaises(SchemaError): 303 a.validate(-1) 304 with self.assertRaises(SchemaError): 305 a.validate(0x10000000000000000) 306 fields.SmallUnsignedInteger(minimum=1) 307 fields.SmallUnsignedInteger(maximum=1) 308 fields.SmallUnsignedInteger(maximum=0xffffffffffffffff) 309 fields.SmallUnsignedInteger(minimum=0) 310 with self.assertRaises(ValueError): 311 fields.SmallUnsignedInteger(maximum=0x10000000000000000) 312 with self.assertRaises(ValueError): 313 fields.SmallUnsignedInteger(minimum=-1) 314 with self.assertRaises(TypeError): 315 fields.SmallUnsignedInteger(maximum=None) 316 with self.assertRaises(TypeError): 317 fields.SmallUnsignedInteger(minimum=None) 318 319 def test_object(self): 320 a = fields.Object(Piwo, optional=True) 321 a.validate(None) 322 a.validate(Piwo()) 323 with self.assertRaises(SchemaError): 324 a.validate('piwo') 325 with self.assertRaises(SchemaError): 326 a.validate(Zlew()) 327 self.assertIsInstance(a.load('piwo'), Piwo) 328 with self.assertRaises(SchemaError): 329 a.load('zlew') 330 self.assertEqual(a.load(None), None) 331 self.assertEqual(a.dump(Piwo()), 'piwo') 332 self.assertEqual(a.dump(None), None) 333 334 a = fields.Object(Zlew) 335 a.validate(Zlew()) 336 with self.assertRaises(SchemaError): 337 a.validate('zlew') 338 with self.assertRaises(SchemaError): 339 a.validate(Piwo()) 340 with self.assertRaises(SchemaError): 341 a.validate(None) 342 self.assertIsInstance(a.load('zlew'), Zlew) 343 with self.assertRaises(SchemaError): 344 a.load('piwo') 345 with self.assertRaises(SchemaError): 346 a.load(None) 347 self.assertEqual(a.dump(Zlew()), 'zlew') 348 349 fields.Object(Zlew, default=Zlew()) 350 with self.assertRaises(SchemaError): 351 fields.Object(Zlew, default=Piwo()) 352 353 def test_list(self): 354 a = fields.List(fields.Object(Piwo)) 355 a.validate([]) 356 a.validate([Piwo()]) 357 a.validate([Piwo(), Piwo(), Piwo()]) 358 with self.assertRaises(SchemaError): 359 a.validate(Piwo()) 360 with self.assertRaises(SchemaError): 361 a.validate(set()) 362 with self.assertRaises(SchemaError): 363 a.validate(None) 364 with self.assertRaises(SchemaError): 365 a.validate([Piwo(), Zlew(), Piwo()]) 366 with self.assertRaises(SchemaError): 367 a.validate([Piwo(), None]) 368 self.assertEqual(a.load([]), []) 369 self.assertEqual(a.load(['piwo', 'piwo']), [Piwo(), Piwo()]) 370 with self.assertRaises(SchemaError): 371 a.validate(a.load({})) 372 with self.assertRaises(SchemaError): 373 a.validate(a.load(None)) 374 with self.assertRaises(SchemaError): 375 a.validate(a.load('piwo')) 376 with self.assertRaises(SchemaError): 377 a.validate(a.load(['zlew'])) 378 with self.assertRaises(SchemaError): 379 a.validate(a.load(['piwo', None])) 380 self.assertEqual(a.dump([]), []) 381 self.assertEqual(a.dump([Piwo(), Piwo()]), ['piwo', 'piwo']) 382 fields.List(fields.Integer(), default=[1, 2, 3]) 383 384 def test_set(self): 385 a = fields.Set(fields.Object(Piwo)) 386 a.validate(set()) 387 a.validate({Piwo()}) 388 with self.assertRaises(SchemaError): 389 a.validate(Piwo()) 390 with self.assertRaises(SchemaError): 391 a.validate([]) 392 with self.assertRaises(SchemaError): 393 a.validate(None) 394 with self.assertRaises(SchemaError): 395 a.validate({Piwo(), Zlew()}) 396 with self.assertRaises(SchemaError): 397 a.validate({Piwo(), None}) 398 self.assertEqual(a.load([]), set()) 399 self.assertEqual(a.load(['piwo']), {Piwo()}) 400 with self.assertRaises(SchemaError): 401 a.validate(a.load({})) 402 with self.assertRaises(SchemaError): 403 a.validate(a.load(None)) 404 with self.assertRaises(SchemaError): 405 a.validate(a.load('piwo')) 406 with self.assertRaises(SchemaError): 407 a.validate(a.load(['zlew'])) 408 with self.assertRaises(SchemaError): 409 a.validate(a.load(['piwo', None])) 410 self.assertEqual(a.dump({}), []) 411 self.assertEqual(a.dump({Piwo()}), ['piwo']) 412 fields.Set(fields.Integer(), default={1, 2, 3}) 413 414 def test_map(self): 415 a = fields.Map(fields.Object(Piwo), fields.Object(Zlew)) 416 a.validate({}) 417 a.validate({Piwo(): Zlew()}) 418 with self.assertRaises(SchemaError): 419 a.validate(Piwo()) 420 with self.assertRaises(SchemaError): 421 a.validate(Zlew()) 422 with self.assertRaises(SchemaError): 423 a.validate([]) 424 with self.assertRaises(SchemaError): 425 a.validate(None) 426 with self.assertRaises(SchemaError): 427 a.validate({Piwo(): Piwo()}) 428 with self.assertRaises(SchemaError): 429 a.validate({Zlew(): Zlew()}) 430 with self.assertRaises(SchemaError): 431 a.validate({Zlew(): Piwo()}) 432 with self.assertRaises(SchemaError): 433 a.validate({Piwo(): None}) 434 with self.assertRaises(SchemaError): 435 a.validate({None: Zlew()}) 436 self.assertEqual(a.load({}), {}) 437 self.assertEqual(a.load({'piwo': 'zlew'}), {Piwo(): Zlew()}) 438 with self.assertRaises(SchemaError): 439 a.validate(a.load([])) 440 with self.assertRaises(SchemaError): 441 a.validate(a.load(None)) 442 with self.assertRaises(SchemaError): 443 a.validate(a.load('piwo')) 444 with self.assertRaises(SchemaError): 445 a.validate(a.load({'piwo': 'piwo'})) 446 with self.assertRaises(SchemaError): 447 a.validate(a.load({'piwo', 'zlew'})) 448 self.assertEqual(a.dump({}), {}) 449 self.assertEqual(a.dump({Piwo(): Zlew()}), {'piwo': 'zlew'}) 450 fields.Map(fields.Integer(), fields.String(), default={1: 'a'}) 451 452 def test_enum(self): 453 a = fields.Enum(ZlewType) 454 a.validate(ZlewType.ZLEW) 455 with self.assertRaises(SchemaError): 456 a.validate('ZLEW') 457 with self.assertRaises(SchemaError): 458 a.validate('zlewzlewzlew') 459 self.assertEqual(a.dump(ZlewType.ZLEW), 'ZLEW') 460 self.assertIsInstance(a.dump(ZlewType.ZLEW), six.text_type) 461 self.assertIs(a.load('TURBOZLEW'), ZlewType.TURBOZLEW) 462 with self.assertRaises(SchemaError): 463 a.load(2) 464 with self.assertRaises(SchemaError): 465 a.load('zlewzlewzlew') 466 with self.assertRaises(SchemaError): 467 a.load('PIETROZLEW') 468 with self.assertRaises(TypeError): 469 fields.Enum(int) 470 471 def test_exception(self): 472 a = fields.Object(VelesException) 473 a.validate(VelesException('abc', 'def')) 474 a.validate(SchemaError()) 475 with self.assertRaises(SchemaError): 476 a.validate('zlew') 477 with self.assertRaises(SchemaError): 478 a.validate(Exception()) 479 de = a.dump(VelesException('abc', 'def')) 480 self.assertEqual(de, { 481 'type': 'abc', 482 'message': 'def', 483 }) 484 for k, v in de.items(): 485 self.assertIsInstance(k, six.text_type) 486 self.assertIsInstance(v, six.text_type) 487 de = a.dump(SchemaError()) 488 self.assertEqual(de, { 489 'type': 'schema_error', 490 'message': SchemaError.msg, 491 }) 492 for k, v in de.items(): 493 self.assertIsInstance(k, six.text_type) 494 self.assertIsInstance(v, six.text_type) 495 exc = a.load({ 496 'type': 'abc', 497 'message': 'def', 498 }) 499 self.assertIs(type(exc), VelesException) 500 self.assertEqual(exc.code, 'abc') 501 self.assertEqual(exc.msg, 'def') 502 exc = a.load({ 503 'type': 'schema_error', 504 'message': 'ghi', 505 }) 506 self.assertIs(type(exc), SchemaError) 507 self.assertEqual(exc.code, 'schema_error') 508 self.assertEqual(exc.msg, 'ghi') 509 with self.assertRaises(SchemaError): 510 a.load([]) 511 with self.assertRaises(SchemaError): 512 a.load({}) 513 with self.assertRaises(SchemaError): 514 a.load({'type': 'abc', 'message': 'def', 'hgw': 'zlew'}) 515 with self.assertRaises(SchemaError): 516 a.load({'type': b'zlew', 'message': 'def'}) 517 with self.assertRaises(SchemaError): 518 a.load({'type': 'zlew', 'message': b'def'}) 519