OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 2 # |
| 3 # Copyright 2010 Google Inc. |
| 4 # |
| 5 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 # you may not use this file except in compliance with the License. |
| 7 # You may obtain a copy of the License at |
| 8 # |
| 9 # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 # |
| 11 # Unless required by applicable law or agreed to in writing, software |
| 12 # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 # See the License for the specific language governing permissions and |
| 15 # limitations under the License. |
| 16 # |
| 17 |
| 18 """Tests for apitools.base.protorpclite.messages.""" |
| 19 import pickle |
| 20 import re |
| 21 import sys |
| 22 import types |
| 23 import unittest |
| 24 |
| 25 import six |
| 26 |
| 27 from apitools.base.protorpclite import descriptor |
| 28 from apitools.base.protorpclite import message_types |
| 29 from apitools.base.protorpclite import messages |
| 30 from apitools.base.protorpclite import test_util |
| 31 |
| 32 # This package plays lots of games with modifying global variables inside |
| 33 # test cases. Hence: |
| 34 # pylint:disable=function-redefined |
| 35 # pylint:disable=global-variable-not-assigned |
| 36 # pylint:disable=global-variable-undefined |
| 37 # pylint:disable=redefined-outer-name |
| 38 # pylint:disable=undefined-variable |
| 39 # pylint:disable=unused-variable |
| 40 # pylint:disable=too-many-lines |
| 41 |
| 42 |
| 43 class ModuleInterfaceTest(test_util.ModuleInterfaceTest, |
| 44 test_util.TestCase): |
| 45 |
| 46 MODULE = messages |
| 47 |
| 48 |
| 49 class ValidationErrorTest(test_util.TestCase): |
| 50 |
| 51 def testStr_NoFieldName(self): |
| 52 """Test string version of ValidationError when no name provided.""" |
| 53 self.assertEquals('Validation error', |
| 54 str(messages.ValidationError('Validation error'))) |
| 55 |
| 56 def testStr_FieldName(self): |
| 57 """Test string version of ValidationError when no name provided.""" |
| 58 validation_error = messages.ValidationError('Validation error') |
| 59 validation_error.field_name = 'a_field' |
| 60 self.assertEquals('Validation error', str(validation_error)) |
| 61 |
| 62 |
| 63 class EnumTest(test_util.TestCase): |
| 64 |
| 65 def setUp(self): |
| 66 """Set up tests.""" |
| 67 # Redefine Color class in case so that changes to it (an |
| 68 # error) in one test does not affect other tests. |
| 69 global Color # pylint:disable=global-variable-not-assigned |
| 70 |
| 71 # pylint:disable=unused-variable |
| 72 class Color(messages.Enum): |
| 73 RED = 20 |
| 74 ORANGE = 2 |
| 75 YELLOW = 40 |
| 76 GREEN = 4 |
| 77 BLUE = 50 |
| 78 INDIGO = 5 |
| 79 VIOLET = 80 |
| 80 |
| 81 def testNames(self): |
| 82 """Test that names iterates over enum names.""" |
| 83 self.assertEquals( |
| 84 set(['BLUE', 'GREEN', 'INDIGO', 'ORANGE', 'RED', |
| 85 'VIOLET', 'YELLOW']), |
| 86 set(Color.names())) |
| 87 |
| 88 def testNumbers(self): |
| 89 """Tests that numbers iterates of enum numbers.""" |
| 90 self.assertEquals(set([2, 4, 5, 20, 40, 50, 80]), set(Color.numbers())) |
| 91 |
| 92 def testIterate(self): |
| 93 """Test that __iter__ iterates over all enum values.""" |
| 94 self.assertEquals(set(Color), |
| 95 set([Color.RED, |
| 96 Color.ORANGE, |
| 97 Color.YELLOW, |
| 98 Color.GREEN, |
| 99 Color.BLUE, |
| 100 Color.INDIGO, |
| 101 Color.VIOLET])) |
| 102 |
| 103 def testNaturalOrder(self): |
| 104 """Test that natural order enumeration is in numeric order.""" |
| 105 self.assertEquals([Color.ORANGE, |
| 106 Color.GREEN, |
| 107 Color.INDIGO, |
| 108 Color.RED, |
| 109 Color.YELLOW, |
| 110 Color.BLUE, |
| 111 Color.VIOLET], |
| 112 sorted(Color)) |
| 113 |
| 114 def testByName(self): |
| 115 """Test look-up by name.""" |
| 116 self.assertEquals(Color.RED, Color.lookup_by_name('RED')) |
| 117 self.assertRaises(KeyError, Color.lookup_by_name, 20) |
| 118 self.assertRaises(KeyError, Color.lookup_by_name, Color.RED) |
| 119 |
| 120 def testByNumber(self): |
| 121 """Test look-up by number.""" |
| 122 self.assertRaises(KeyError, Color.lookup_by_number, 'RED') |
| 123 self.assertEquals(Color.RED, Color.lookup_by_number(20)) |
| 124 self.assertRaises(KeyError, Color.lookup_by_number, Color.RED) |
| 125 |
| 126 def testConstructor(self): |
| 127 """Test that constructor look-up by name or number.""" |
| 128 self.assertEquals(Color.RED, Color('RED')) |
| 129 self.assertEquals(Color.RED, Color(u'RED')) |
| 130 self.assertEquals(Color.RED, Color(20)) |
| 131 if six.PY2: |
| 132 self.assertEquals(Color.RED, Color(long(20))) |
| 133 self.assertEquals(Color.RED, Color(Color.RED)) |
| 134 self.assertRaises(TypeError, Color, 'Not exists') |
| 135 self.assertRaises(TypeError, Color, 'Red') |
| 136 self.assertRaises(TypeError, Color, 100) |
| 137 self.assertRaises(TypeError, Color, 10.0) |
| 138 |
| 139 def testLen(self): |
| 140 """Test that len function works to count enums.""" |
| 141 self.assertEquals(7, len(Color)) |
| 142 |
| 143 def testNoSubclasses(self): |
| 144 """Test that it is not possible to sub-class enum classes.""" |
| 145 def declare_subclass(): |
| 146 class MoreColor(Color): |
| 147 pass |
| 148 self.assertRaises(messages.EnumDefinitionError, |
| 149 declare_subclass) |
| 150 |
| 151 def testClassNotMutable(self): |
| 152 """Test that enum classes themselves are not mutable.""" |
| 153 self.assertRaises(AttributeError, |
| 154 setattr, |
| 155 Color, |
| 156 'something_new', |
| 157 10) |
| 158 |
| 159 def testInstancesMutable(self): |
| 160 """Test that enum instances are not mutable.""" |
| 161 self.assertRaises(TypeError, |
| 162 setattr, |
| 163 Color.RED, |
| 164 'something_new', |
| 165 10) |
| 166 |
| 167 def testDefEnum(self): |
| 168 """Test def_enum works by building enum class from dict.""" |
| 169 WeekDay = messages.Enum.def_enum({'Monday': 1, |
| 170 'Tuesday': 2, |
| 171 'Wednesday': 3, |
| 172 'Thursday': 4, |
| 173 'Friday': 6, |
| 174 'Saturday': 7, |
| 175 'Sunday': 8}, |
| 176 'WeekDay') |
| 177 self.assertEquals('Wednesday', WeekDay(3).name) |
| 178 self.assertEquals(6, WeekDay('Friday').number) |
| 179 self.assertEquals(WeekDay.Sunday, WeekDay('Sunday')) |
| 180 |
| 181 def testNonInt(self): |
| 182 """Test that non-integer values rejection by enum def.""" |
| 183 self.assertRaises(messages.EnumDefinitionError, |
| 184 messages.Enum.def_enum, |
| 185 {'Bad': '1'}, |
| 186 'BadEnum') |
| 187 |
| 188 def testNegativeInt(self): |
| 189 """Test that negative numbers rejection by enum def.""" |
| 190 self.assertRaises(messages.EnumDefinitionError, |
| 191 messages.Enum.def_enum, |
| 192 {'Bad': -1}, |
| 193 'BadEnum') |
| 194 |
| 195 def testLowerBound(self): |
| 196 """Test that zero is accepted by enum def.""" |
| 197 class NotImportant(messages.Enum): |
| 198 """Testing for value zero""" |
| 199 VALUE = 0 |
| 200 |
| 201 self.assertEquals(0, int(NotImportant.VALUE)) |
| 202 |
| 203 def testTooLargeInt(self): |
| 204 """Test that numbers too large are rejected.""" |
| 205 self.assertRaises(messages.EnumDefinitionError, |
| 206 messages.Enum.def_enum, |
| 207 {'Bad': (2 ** 29)}, |
| 208 'BadEnum') |
| 209 |
| 210 def testRepeatedInt(self): |
| 211 """Test duplicated numbers are forbidden.""" |
| 212 self.assertRaises(messages.EnumDefinitionError, |
| 213 messages.Enum.def_enum, |
| 214 {'Ok': 1, 'Repeated': 1}, |
| 215 'BadEnum') |
| 216 |
| 217 def testStr(self): |
| 218 """Test converting to string.""" |
| 219 self.assertEquals('RED', str(Color.RED)) |
| 220 self.assertEquals('ORANGE', str(Color.ORANGE)) |
| 221 |
| 222 def testInt(self): |
| 223 """Test converting to int.""" |
| 224 self.assertEquals(20, int(Color.RED)) |
| 225 self.assertEquals(2, int(Color.ORANGE)) |
| 226 |
| 227 def testRepr(self): |
| 228 """Test enum representation.""" |
| 229 self.assertEquals('Color(RED, 20)', repr(Color.RED)) |
| 230 self.assertEquals('Color(YELLOW, 40)', repr(Color.YELLOW)) |
| 231 |
| 232 def testDocstring(self): |
| 233 """Test that docstring is supported ok.""" |
| 234 class NotImportant(messages.Enum): |
| 235 """I have a docstring.""" |
| 236 |
| 237 VALUE1 = 1 |
| 238 |
| 239 self.assertEquals('I have a docstring.', NotImportant.__doc__) |
| 240 |
| 241 def testDeleteEnumValue(self): |
| 242 """Test that enum values cannot be deleted.""" |
| 243 self.assertRaises(TypeError, delattr, Color, 'RED') |
| 244 |
| 245 def testEnumName(self): |
| 246 """Test enum name.""" |
| 247 module_name = test_util.get_module_name(EnumTest) |
| 248 self.assertEquals('%s.Color' % module_name, Color.definition_name()) |
| 249 self.assertEquals(module_name, Color.outer_definition_name()) |
| 250 self.assertEquals(module_name, Color.definition_package()) |
| 251 |
| 252 def testDefinitionName_OverrideModule(self): |
| 253 """Test enum module is overriden by module package name.""" |
| 254 global package |
| 255 try: |
| 256 package = 'my.package' |
| 257 self.assertEquals('my.package.Color', Color.definition_name()) |
| 258 self.assertEquals('my.package', Color.outer_definition_name()) |
| 259 self.assertEquals('my.package', Color.definition_package()) |
| 260 finally: |
| 261 del package |
| 262 |
| 263 def testDefinitionName_NoModule(self): |
| 264 """Test what happens when there is no module for enum.""" |
| 265 class Enum1(messages.Enum): |
| 266 pass |
| 267 |
| 268 original_modules = sys.modules |
| 269 sys.modules = dict(sys.modules) |
| 270 try: |
| 271 del sys.modules[__name__] |
| 272 self.assertEquals('Enum1', Enum1.definition_name()) |
| 273 self.assertEquals(None, Enum1.outer_definition_name()) |
| 274 self.assertEquals(None, Enum1.definition_package()) |
| 275 self.assertEquals(six.text_type, type(Enum1.definition_name())) |
| 276 finally: |
| 277 sys.modules = original_modules |
| 278 |
| 279 def testDefinitionName_Nested(self): |
| 280 """Test nested Enum names.""" |
| 281 class MyMessage(messages.Message): |
| 282 |
| 283 class NestedEnum(messages.Enum): |
| 284 |
| 285 pass |
| 286 |
| 287 class NestedMessage(messages.Message): |
| 288 |
| 289 class NestedEnum(messages.Enum): |
| 290 |
| 291 pass |
| 292 |
| 293 module_name = test_util.get_module_name(EnumTest) |
| 294 self.assertEquals('%s.MyMessage.NestedEnum' % module_name, |
| 295 MyMessage.NestedEnum.definition_name()) |
| 296 self.assertEquals('%s.MyMessage' % module_name, |
| 297 MyMessage.NestedEnum.outer_definition_name()) |
| 298 self.assertEquals(module_name, |
| 299 MyMessage.NestedEnum.definition_package()) |
| 300 |
| 301 self.assertEquals( |
| 302 '%s.MyMessage.NestedMessage.NestedEnum' % module_name, |
| 303 MyMessage.NestedMessage.NestedEnum.definition_name()) |
| 304 self.assertEquals( |
| 305 '%s.MyMessage.NestedMessage' % module_name, |
| 306 MyMessage.NestedMessage.NestedEnum.outer_definition_name()) |
| 307 self.assertEquals( |
| 308 module_name, |
| 309 MyMessage.NestedMessage.NestedEnum.definition_package()) |
| 310 |
| 311 def testMessageDefinition(self): |
| 312 """Test that enumeration knows its enclosing message definition.""" |
| 313 class OuterEnum(messages.Enum): |
| 314 pass |
| 315 |
| 316 self.assertEquals(None, OuterEnum.message_definition()) |
| 317 |
| 318 class OuterMessage(messages.Message): |
| 319 |
| 320 class InnerEnum(messages.Enum): |
| 321 pass |
| 322 |
| 323 self.assertEquals( |
| 324 OuterMessage, OuterMessage.InnerEnum.message_definition()) |
| 325 |
| 326 def testComparison(self): |
| 327 """Test comparing various enums to different types.""" |
| 328 class Enum1(messages.Enum): |
| 329 VAL1 = 1 |
| 330 VAL2 = 2 |
| 331 |
| 332 class Enum2(messages.Enum): |
| 333 VAL1 = 1 |
| 334 |
| 335 self.assertEquals(Enum1.VAL1, Enum1.VAL1) |
| 336 self.assertNotEquals(Enum1.VAL1, Enum1.VAL2) |
| 337 self.assertNotEquals(Enum1.VAL1, Enum2.VAL1) |
| 338 self.assertNotEquals(Enum1.VAL1, 'VAL1') |
| 339 self.assertNotEquals(Enum1.VAL1, 1) |
| 340 self.assertNotEquals(Enum1.VAL1, 2) |
| 341 self.assertNotEquals(Enum1.VAL1, None) |
| 342 self.assertNotEquals(Enum1.VAL1, Enum2.VAL1) |
| 343 |
| 344 self.assertTrue(Enum1.VAL1 < Enum1.VAL2) |
| 345 self.assertTrue(Enum1.VAL2 > Enum1.VAL1) |
| 346 |
| 347 self.assertNotEquals(1, Enum2.VAL1) |
| 348 |
| 349 def testPickle(self): |
| 350 """Testing pickling and unpickling of Enum instances.""" |
| 351 colors = list(Color) |
| 352 unpickled = pickle.loads(pickle.dumps(colors)) |
| 353 self.assertEquals(colors, unpickled) |
| 354 # Unpickling shouldn't create new enum instances. |
| 355 for i, color in enumerate(colors): |
| 356 self.assertTrue(color is unpickled[i]) |
| 357 |
| 358 |
| 359 class FieldListTest(test_util.TestCase): |
| 360 |
| 361 def setUp(self): |
| 362 self.integer_field = messages.IntegerField(1, repeated=True) |
| 363 |
| 364 def testConstructor(self): |
| 365 self.assertEquals([1, 2, 3], |
| 366 messages.FieldList(self.integer_field, [1, 2, 3])) |
| 367 self.assertEquals([1, 2, 3], |
| 368 messages.FieldList(self.integer_field, (1, 2, 3))) |
| 369 self.assertEquals([], messages.FieldList(self.integer_field, [])) |
| 370 |
| 371 def testNone(self): |
| 372 self.assertRaises(TypeError, messages.FieldList, |
| 373 self.integer_field, None) |
| 374 |
| 375 def testDoNotAutoConvertString(self): |
| 376 string_field = messages.StringField(1, repeated=True) |
| 377 self.assertRaises(messages.ValidationError, |
| 378 messages.FieldList, string_field, 'abc') |
| 379 |
| 380 def testConstructorCopies(self): |
| 381 a_list = [1, 3, 6] |
| 382 field_list = messages.FieldList(self.integer_field, a_list) |
| 383 self.assertFalse(a_list is field_list) |
| 384 self.assertFalse(field_list is |
| 385 messages.FieldList(self.integer_field, field_list)) |
| 386 |
| 387 def testNonRepeatedField(self): |
| 388 self.assertRaisesWithRegexpMatch( |
| 389 messages.FieldDefinitionError, |
| 390 'FieldList may only accept repeated fields', |
| 391 messages.FieldList, |
| 392 messages.IntegerField(1), |
| 393 []) |
| 394 |
| 395 def testConstructor_InvalidValues(self): |
| 396 self.assertRaisesWithRegexpMatch( |
| 397 messages.ValidationError, |
| 398 re.escape("Expected type %r " |
| 399 "for IntegerField, found 1 (type %r)" |
| 400 % (six.integer_types, str)), |
| 401 messages.FieldList, self.integer_field, ["1", "2", "3"]) |
| 402 |
| 403 def testConstructor_Scalars(self): |
| 404 self.assertRaisesWithRegexpMatch( |
| 405 messages.ValidationError, |
| 406 "IntegerField is repeated. Found: 3", |
| 407 messages.FieldList, self.integer_field, 3) |
| 408 |
| 409 self.assertRaisesWithRegexpMatch( |
| 410 messages.ValidationError, |
| 411 ("IntegerField is repeated. Found: " |
| 412 "<(list[_]?|sequence)iterator object"), |
| 413 messages.FieldList, self.integer_field, iter([1, 2, 3])) |
| 414 |
| 415 def testSetSlice(self): |
| 416 field_list = messages.FieldList(self.integer_field, [1, 2, 3, 4, 5]) |
| 417 field_list[1:3] = [10, 20] |
| 418 self.assertEquals([1, 10, 20, 4, 5], field_list) |
| 419 |
| 420 def testSetSlice_InvalidValues(self): |
| 421 field_list = messages.FieldList(self.integer_field, [1, 2, 3, 4, 5]) |
| 422 |
| 423 def setslice(): |
| 424 field_list[1:3] = ['10', '20'] |
| 425 |
| 426 msg_re = re.escape("Expected type %r " |
| 427 "for IntegerField, found 10 (type %r)" |
| 428 % (six.integer_types, str)) |
| 429 self.assertRaisesWithRegexpMatch( |
| 430 messages.ValidationError, |
| 431 msg_re, |
| 432 setslice) |
| 433 |
| 434 def testSetItem(self): |
| 435 field_list = messages.FieldList(self.integer_field, [2]) |
| 436 field_list[0] = 10 |
| 437 self.assertEquals([10], field_list) |
| 438 |
| 439 def testSetItem_InvalidValues(self): |
| 440 field_list = messages.FieldList(self.integer_field, [2]) |
| 441 |
| 442 def setitem(): |
| 443 field_list[0] = '10' |
| 444 self.assertRaisesWithRegexpMatch( |
| 445 messages.ValidationError, |
| 446 re.escape("Expected type %r " |
| 447 "for IntegerField, found 10 (type %r)" |
| 448 % (six.integer_types, str)), |
| 449 setitem) |
| 450 |
| 451 def testAppend(self): |
| 452 field_list = messages.FieldList(self.integer_field, [2]) |
| 453 field_list.append(10) |
| 454 self.assertEquals([2, 10], field_list) |
| 455 |
| 456 def testAppend_InvalidValues(self): |
| 457 field_list = messages.FieldList(self.integer_field, [2]) |
| 458 field_list.name = 'a_field' |
| 459 |
| 460 def append(): |
| 461 field_list.append('10') |
| 462 self.assertRaisesWithRegexpMatch( |
| 463 messages.ValidationError, |
| 464 re.escape("Expected type %r " |
| 465 "for IntegerField, found 10 (type %r)" |
| 466 % (six.integer_types, str)), |
| 467 append) |
| 468 |
| 469 def testExtend(self): |
| 470 field_list = messages.FieldList(self.integer_field, [2]) |
| 471 field_list.extend([10]) |
| 472 self.assertEquals([2, 10], field_list) |
| 473 |
| 474 def testExtend_InvalidValues(self): |
| 475 field_list = messages.FieldList(self.integer_field, [2]) |
| 476 |
| 477 def extend(): |
| 478 field_list.extend(['10']) |
| 479 self.assertRaisesWithRegexpMatch( |
| 480 messages.ValidationError, |
| 481 re.escape("Expected type %r " |
| 482 "for IntegerField, found 10 (type %r)" |
| 483 % (six.integer_types, str)), |
| 484 extend) |
| 485 |
| 486 def testInsert(self): |
| 487 field_list = messages.FieldList(self.integer_field, [2, 3]) |
| 488 field_list.insert(1, 10) |
| 489 self.assertEquals([2, 10, 3], field_list) |
| 490 |
| 491 def testInsert_InvalidValues(self): |
| 492 field_list = messages.FieldList(self.integer_field, [2, 3]) |
| 493 |
| 494 def insert(): |
| 495 field_list.insert(1, '10') |
| 496 self.assertRaisesWithRegexpMatch( |
| 497 messages.ValidationError, |
| 498 re.escape("Expected type %r " |
| 499 "for IntegerField, found 10 (type %r)" |
| 500 % (six.integer_types, str)), |
| 501 insert) |
| 502 |
| 503 def testPickle(self): |
| 504 """Testing pickling and unpickling of FieldList instances.""" |
| 505 field_list = messages.FieldList(self.integer_field, [1, 2, 3, 4, 5]) |
| 506 unpickled = pickle.loads(pickle.dumps(field_list)) |
| 507 self.assertEquals(field_list, unpickled) |
| 508 self.assertIsInstance(unpickled.field, messages.IntegerField) |
| 509 self.assertEquals(1, unpickled.field.number) |
| 510 self.assertTrue(unpickled.field.repeated) |
| 511 |
| 512 |
| 513 class FieldTest(test_util.TestCase): |
| 514 |
| 515 def ActionOnAllFieldClasses(self, action): |
| 516 """Test all field classes except Message and Enum. |
| 517 |
| 518 Message and Enum require separate tests. |
| 519 |
| 520 Args: |
| 521 action: Callable that takes the field class as a parameter. |
| 522 """ |
| 523 classes = (messages.IntegerField, |
| 524 messages.FloatField, |
| 525 messages.BooleanField, |
| 526 messages.BytesField, |
| 527 messages.StringField) |
| 528 for field_class in classes: |
| 529 action(field_class) |
| 530 |
| 531 def testNumberAttribute(self): |
| 532 """Test setting the number attribute.""" |
| 533 def action(field_class): |
| 534 # Check range. |
| 535 self.assertRaises(messages.InvalidNumberError, |
| 536 field_class, |
| 537 0) |
| 538 self.assertRaises(messages.InvalidNumberError, |
| 539 field_class, |
| 540 -1) |
| 541 self.assertRaises(messages.InvalidNumberError, |
| 542 field_class, |
| 543 messages.MAX_FIELD_NUMBER + 1) |
| 544 |
| 545 # Check reserved. |
| 546 self.assertRaises(messages.InvalidNumberError, |
| 547 field_class, |
| 548 messages.FIRST_RESERVED_FIELD_NUMBER) |
| 549 self.assertRaises(messages.InvalidNumberError, |
| 550 field_class, |
| 551 messages.LAST_RESERVED_FIELD_NUMBER) |
| 552 self.assertRaises(messages.InvalidNumberError, |
| 553 field_class, |
| 554 '1') |
| 555 |
| 556 # This one should work. |
| 557 field_class(number=1) |
| 558 self.ActionOnAllFieldClasses(action) |
| 559 |
| 560 def testRequiredAndRepeated(self): |
| 561 """Test setting the required and repeated fields.""" |
| 562 def action(field_class): |
| 563 field_class(1, required=True) |
| 564 field_class(1, repeated=True) |
| 565 self.assertRaises(messages.FieldDefinitionError, |
| 566 field_class, |
| 567 1, |
| 568 required=True, |
| 569 repeated=True) |
| 570 self.ActionOnAllFieldClasses(action) |
| 571 |
| 572 def testInvalidVariant(self): |
| 573 """Test field with invalid variants.""" |
| 574 def action(field_class): |
| 575 if field_class is not message_types.DateTimeField: |
| 576 self.assertRaises(messages.InvalidVariantError, |
| 577 field_class, |
| 578 1, |
| 579 variant=messages.Variant.ENUM) |
| 580 self.ActionOnAllFieldClasses(action) |
| 581 |
| 582 def testDefaultVariant(self): |
| 583 """Test that default variant is used when not set.""" |
| 584 def action(field_class): |
| 585 field = field_class(1) |
| 586 self.assertEquals(field_class.DEFAULT_VARIANT, field.variant) |
| 587 |
| 588 self.ActionOnAllFieldClasses(action) |
| 589 |
| 590 def testAlternateVariant(self): |
| 591 """Test that default variant is used when not set.""" |
| 592 field = messages.IntegerField(1, variant=messages.Variant.UINT32) |
| 593 self.assertEquals(messages.Variant.UINT32, field.variant) |
| 594 |
| 595 def testDefaultFields_Single(self): |
| 596 """Test default field is correct type (single).""" |
| 597 defaults = { |
| 598 messages.IntegerField: 10, |
| 599 messages.FloatField: 1.5, |
| 600 messages.BooleanField: False, |
| 601 messages.BytesField: b'abc', |
| 602 messages.StringField: u'abc', |
| 603 } |
| 604 |
| 605 def action(field_class): |
| 606 field_class(1, default=defaults[field_class]) |
| 607 self.ActionOnAllFieldClasses(action) |
| 608 |
| 609 # Run defaults test again checking for str/unicode compatiblity. |
| 610 defaults[messages.StringField] = 'abc' |
| 611 self.ActionOnAllFieldClasses(action) |
| 612 |
| 613 def testStringField_BadUnicodeInDefault(self): |
| 614 """Test binary values in string field.""" |
| 615 self.assertRaisesWithRegexpMatch( |
| 616 messages.InvalidDefaultError, |
| 617 r"Invalid default value for StringField:.*: " |
| 618 r"Field encountered non-ASCII string .*: " |
| 619 r"'ascii' codec can't decode byte 0x89 in position 0: " |
| 620 r"ordinal not in range", |
| 621 messages.StringField, 1, default=b'\x89') |
| 622 |
| 623 def testDefaultFields_InvalidSingle(self): |
| 624 """Test default field is correct type (invalid single).""" |
| 625 def action(field_class): |
| 626 self.assertRaises(messages.InvalidDefaultError, |
| 627 field_class, |
| 628 1, |
| 629 default=object()) |
| 630 self.ActionOnAllFieldClasses(action) |
| 631 |
| 632 def testDefaultFields_InvalidRepeated(self): |
| 633 """Test default field does not accept defaults.""" |
| 634 self.assertRaisesWithRegexpMatch( |
| 635 messages.FieldDefinitionError, |
| 636 'Repeated fields may not have defaults', |
| 637 messages.StringField, 1, repeated=True, default=[1, 2, 3]) |
| 638 |
| 639 def testDefaultFields_None(self): |
| 640 """Test none is always acceptable.""" |
| 641 def action(field_class): |
| 642 field_class(1, default=None) |
| 643 field_class(1, required=True, default=None) |
| 644 field_class(1, repeated=True, default=None) |
| 645 self.ActionOnAllFieldClasses(action) |
| 646 |
| 647 def testDefaultFields_Enum(self): |
| 648 """Test the default for enum fields.""" |
| 649 class Symbol(messages.Enum): |
| 650 |
| 651 ALPHA = 1 |
| 652 BETA = 2 |
| 653 GAMMA = 3 |
| 654 |
| 655 field = messages.EnumField(Symbol, 1, default=Symbol.ALPHA) |
| 656 |
| 657 self.assertEquals(Symbol.ALPHA, field.default) |
| 658 |
| 659 def testDefaultFields_EnumStringDelayedResolution(self): |
| 660 """Test that enum fields resolve default strings.""" |
| 661 field = messages.EnumField( |
| 662 'apitools.base.protorpclite.descriptor.FieldDescriptor.Label', |
| 663 1, |
| 664 default='OPTIONAL') |
| 665 |
| 666 self.assertEquals( |
| 667 descriptor.FieldDescriptor.Label.OPTIONAL, field.default) |
| 668 |
| 669 def testDefaultFields_EnumIntDelayedResolution(self): |
| 670 """Test that enum fields resolve default integers.""" |
| 671 field = messages.EnumField( |
| 672 'apitools.base.protorpclite.descriptor.FieldDescriptor.Label', |
| 673 1, |
| 674 default=2) |
| 675 |
| 676 self.assertEquals( |
| 677 descriptor.FieldDescriptor.Label.REQUIRED, field.default) |
| 678 |
| 679 def testDefaultFields_EnumOkIfTypeKnown(self): |
| 680 """Test enum fields accept valid default values when type is known.""" |
| 681 field = messages.EnumField(descriptor.FieldDescriptor.Label, |
| 682 1, |
| 683 default='REPEATED') |
| 684 |
| 685 self.assertEquals( |
| 686 descriptor.FieldDescriptor.Label.REPEATED, field.default) |
| 687 |
| 688 def testDefaultFields_EnumForceCheckIfTypeKnown(self): |
| 689 """Test that enum fields validate default values if type is known.""" |
| 690 self.assertRaisesWithRegexpMatch(TypeError, |
| 691 'No such value for NOT_A_LABEL in ' |
| 692 'Enum Label', |
| 693 messages.EnumField, |
| 694 descriptor.FieldDescriptor.Label, |
| 695 1, |
| 696 default='NOT_A_LABEL') |
| 697 |
| 698 def testDefaultFields_EnumInvalidDelayedResolution(self): |
| 699 """Test that enum fields raise errors upon delayed resolution error.""" |
| 700 field = messages.EnumField( |
| 701 'apitools.base.protorpclite.descriptor.FieldDescriptor.Label', |
| 702 1, |
| 703 default=200) |
| 704 |
| 705 self.assertRaisesWithRegexpMatch(TypeError, |
| 706 'No such value for 200 in Enum Label', |
| 707 getattr, |
| 708 field, |
| 709 'default') |
| 710 |
| 711 def testValidate_Valid(self): |
| 712 """Test validation of valid values.""" |
| 713 values = { |
| 714 messages.IntegerField: 10, |
| 715 messages.FloatField: 1.5, |
| 716 messages.BooleanField: False, |
| 717 messages.BytesField: b'abc', |
| 718 messages.StringField: u'abc', |
| 719 } |
| 720 |
| 721 def action(field_class): |
| 722 # Optional. |
| 723 field = field_class(1) |
| 724 field.validate(values[field_class]) |
| 725 |
| 726 # Required. |
| 727 field = field_class(1, required=True) |
| 728 field.validate(values[field_class]) |
| 729 |
| 730 # Repeated. |
| 731 field = field_class(1, repeated=True) |
| 732 field.validate([]) |
| 733 field.validate(()) |
| 734 field.validate([values[field_class]]) |
| 735 field.validate((values[field_class],)) |
| 736 |
| 737 # Right value, but not repeated. |
| 738 self.assertRaises(messages.ValidationError, |
| 739 field.validate, |
| 740 values[field_class]) |
| 741 self.assertRaises(messages.ValidationError, |
| 742 field.validate, |
| 743 values[field_class]) |
| 744 |
| 745 self.ActionOnAllFieldClasses(action) |
| 746 |
| 747 def testValidate_Invalid(self): |
| 748 """Test validation of valid values.""" |
| 749 values = { |
| 750 messages.IntegerField: "10", |
| 751 messages.FloatField: "blah", |
| 752 messages.BooleanField: 0, |
| 753 messages.BytesField: 10.20, |
| 754 messages.StringField: 42, |
| 755 } |
| 756 |
| 757 def action(field_class): |
| 758 # Optional. |
| 759 field = field_class(1) |
| 760 self.assertRaises(messages.ValidationError, |
| 761 field.validate, |
| 762 values[field_class]) |
| 763 |
| 764 # Required. |
| 765 field = field_class(1, required=True) |
| 766 self.assertRaises(messages.ValidationError, |
| 767 field.validate, |
| 768 values[field_class]) |
| 769 |
| 770 # Repeated. |
| 771 field = field_class(1, repeated=True) |
| 772 self.assertRaises(messages.ValidationError, |
| 773 field.validate, |
| 774 [values[field_class]]) |
| 775 self.assertRaises(messages.ValidationError, |
| 776 field.validate, |
| 777 (values[field_class],)) |
| 778 self.ActionOnAllFieldClasses(action) |
| 779 |
| 780 def testValidate_None(self): |
| 781 """Test that None is valid for non-required fields.""" |
| 782 def action(field_class): |
| 783 # Optional. |
| 784 field = field_class(1) |
| 785 field.validate(None) |
| 786 |
| 787 # Required. |
| 788 field = field_class(1, required=True) |
| 789 self.assertRaisesWithRegexpMatch(messages.ValidationError, |
| 790 'Required field is missing', |
| 791 field.validate, |
| 792 None) |
| 793 |
| 794 # Repeated. |
| 795 field = field_class(1, repeated=True) |
| 796 field.validate(None) |
| 797 self.assertRaisesWithRegexpMatch( |
| 798 messages.ValidationError, |
| 799 'Repeated values for %s may ' |
| 800 'not be None' % field_class.__name__, |
| 801 field.validate, |
| 802 [None]) |
| 803 self.assertRaises(messages.ValidationError, |
| 804 field.validate, |
| 805 (None,)) |
| 806 self.ActionOnAllFieldClasses(action) |
| 807 |
| 808 def testValidateElement(self): |
| 809 """Test validation of valid values.""" |
| 810 values = { |
| 811 messages.IntegerField: (10, -1, 0), |
| 812 messages.FloatField: (1.5, -1.5, 3), # for json it is all a number |
| 813 messages.BooleanField: (True, False), |
| 814 messages.BytesField: (b'abc',), |
| 815 messages.StringField: (u'abc',), |
| 816 } |
| 817 |
| 818 def action(field_class): |
| 819 # Optional. |
| 820 field = field_class(1) |
| 821 for value in values[field_class]: |
| 822 field.validate_element(value) |
| 823 |
| 824 # Required. |
| 825 field = field_class(1, required=True) |
| 826 for value in values[field_class]: |
| 827 field.validate_element(value) |
| 828 |
| 829 # Repeated. |
| 830 field = field_class(1, repeated=True) |
| 831 self.assertRaises(messages.ValidationError, |
| 832 field.validate_element, |
| 833 []) |
| 834 self.assertRaises(messages.ValidationError, |
| 835 field.validate_element, |
| 836 ()) |
| 837 for value in values[field_class]: |
| 838 field.validate_element(value) |
| 839 |
| 840 # Right value, but repeated. |
| 841 self.assertRaises(messages.ValidationError, |
| 842 field.validate_element, |
| 843 list(values[field_class])) # testing list |
| 844 self.assertRaises(messages.ValidationError, |
| 845 field.validate_element, |
| 846 values[field_class]) # testing tuple |
| 847 |
| 848 self.ActionOnAllFieldClasses(action) |
| 849 |
| 850 def testValidateCastingElement(self): |
| 851 field = messages.FloatField(1) |
| 852 self.assertEquals(type(field.validate_element(12)), float) |
| 853 self.assertEquals(type(field.validate_element(12.0)), float) |
| 854 # pylint: disable=redefined-variable-type |
| 855 field = messages.IntegerField(1) |
| 856 self.assertEquals(type(field.validate_element(12)), int) |
| 857 self.assertRaises(messages.ValidationError, |
| 858 field.validate_element, |
| 859 12.0) # should fails from float to int |
| 860 |
| 861 def testReadOnly(self): |
| 862 """Test that objects are all read-only.""" |
| 863 def action(field_class): |
| 864 field = field_class(10) |
| 865 self.assertRaises(AttributeError, |
| 866 setattr, |
| 867 field, |
| 868 'number', |
| 869 20) |
| 870 self.assertRaises(AttributeError, |
| 871 setattr, |
| 872 field, |
| 873 'anything_else', |
| 874 'whatever') |
| 875 self.ActionOnAllFieldClasses(action) |
| 876 |
| 877 def testMessageField(self): |
| 878 """Test the construction of message fields.""" |
| 879 self.assertRaises(messages.FieldDefinitionError, |
| 880 messages.MessageField, |
| 881 str, |
| 882 10) |
| 883 |
| 884 self.assertRaises(messages.FieldDefinitionError, |
| 885 messages.MessageField, |
| 886 messages.Message, |
| 887 10) |
| 888 |
| 889 class MyMessage(messages.Message): |
| 890 pass |
| 891 |
| 892 field = messages.MessageField(MyMessage, 10) |
| 893 self.assertEquals(MyMessage, field.type) |
| 894 |
| 895 def testMessageField_ForwardReference(self): |
| 896 """Test the construction of forward reference message fields.""" |
| 897 global MyMessage |
| 898 global ForwardMessage |
| 899 try: |
| 900 class MyMessage(messages.Message): |
| 901 |
| 902 self_reference = messages.MessageField('MyMessage', 1) |
| 903 forward = messages.MessageField('ForwardMessage', 2) |
| 904 nested = messages.MessageField( |
| 905 'ForwardMessage.NestedMessage', 3) |
| 906 inner = messages.MessageField('Inner', 4) |
| 907 |
| 908 class Inner(messages.Message): |
| 909 |
| 910 sibling = messages.MessageField('Sibling', 1) |
| 911 |
| 912 class Sibling(messages.Message): |
| 913 |
| 914 pass |
| 915 |
| 916 class ForwardMessage(messages.Message): |
| 917 |
| 918 class NestedMessage(messages.Message): |
| 919 |
| 920 pass |
| 921 |
| 922 self.assertEquals(MyMessage, |
| 923 MyMessage.field_by_name('self_reference').type) |
| 924 |
| 925 self.assertEquals(ForwardMessage, |
| 926 MyMessage.field_by_name('forward').type) |
| 927 |
| 928 self.assertEquals(ForwardMessage.NestedMessage, |
| 929 MyMessage.field_by_name('nested').type) |
| 930 |
| 931 self.assertEquals(MyMessage.Inner, |
| 932 MyMessage.field_by_name('inner').type) |
| 933 |
| 934 self.assertEquals(MyMessage.Sibling, |
| 935 MyMessage.Inner.field_by_name('sibling').type) |
| 936 finally: |
| 937 try: |
| 938 del MyMessage |
| 939 del ForwardMessage |
| 940 except: # pylint:disable=bare-except |
| 941 pass |
| 942 |
| 943 def testMessageField_WrongType(self): |
| 944 """Test that forward referencing the wrong type raises an error.""" |
| 945 global AnEnum |
| 946 try: |
| 947 class AnEnum(messages.Enum): |
| 948 pass |
| 949 |
| 950 class AnotherMessage(messages.Message): |
| 951 |
| 952 a_field = messages.MessageField('AnEnum', 1) |
| 953 |
| 954 self.assertRaises(messages.FieldDefinitionError, |
| 955 getattr, |
| 956 AnotherMessage.field_by_name('a_field'), |
| 957 'type') |
| 958 finally: |
| 959 del AnEnum |
| 960 |
| 961 def testMessageFieldValidate(self): |
| 962 """Test validation on message field.""" |
| 963 class MyMessage(messages.Message): |
| 964 pass |
| 965 |
| 966 class AnotherMessage(messages.Message): |
| 967 pass |
| 968 |
| 969 field = messages.MessageField(MyMessage, 10) |
| 970 field.validate(MyMessage()) |
| 971 |
| 972 self.assertRaises(messages.ValidationError, |
| 973 field.validate, |
| 974 AnotherMessage()) |
| 975 |
| 976 def testMessageFieldMessageType(self): |
| 977 """Test message_type property.""" |
| 978 class MyMessage(messages.Message): |
| 979 pass |
| 980 |
| 981 class HasMessage(messages.Message): |
| 982 field = messages.MessageField(MyMessage, 1) |
| 983 |
| 984 self.assertEqual(HasMessage.field.type, HasMessage.field.message_type) |
| 985 |
| 986 def testMessageFieldValueFromMessage(self): |
| 987 class MyMessage(messages.Message): |
| 988 pass |
| 989 |
| 990 class HasMessage(messages.Message): |
| 991 field = messages.MessageField(MyMessage, 1) |
| 992 |
| 993 instance = MyMessage() |
| 994 |
| 995 self.assertTrue( |
| 996 instance is HasMessage.field.value_from_message(instance)) |
| 997 |
| 998 def testMessageFieldValueFromMessageWrongType(self): |
| 999 class MyMessage(messages.Message): |
| 1000 pass |
| 1001 |
| 1002 class HasMessage(messages.Message): |
| 1003 field = messages.MessageField(MyMessage, 1) |
| 1004 |
| 1005 self.assertRaisesWithRegexpMatch( |
| 1006 messages.DecodeError, |
| 1007 'Expected type MyMessage, got int: 10', |
| 1008 HasMessage.field.value_from_message, 10) |
| 1009 |
| 1010 def testMessageFieldValueToMessage(self): |
| 1011 class MyMessage(messages.Message): |
| 1012 pass |
| 1013 |
| 1014 class HasMessage(messages.Message): |
| 1015 field = messages.MessageField(MyMessage, 1) |
| 1016 |
| 1017 instance = MyMessage() |
| 1018 |
| 1019 self.assertTrue( |
| 1020 instance is HasMessage.field.value_to_message(instance)) |
| 1021 |
| 1022 def testMessageFieldValueToMessageWrongType(self): |
| 1023 class MyMessage(messages.Message): |
| 1024 pass |
| 1025 |
| 1026 class MyOtherMessage(messages.Message): |
| 1027 pass |
| 1028 |
| 1029 class HasMessage(messages.Message): |
| 1030 field = messages.MessageField(MyMessage, 1) |
| 1031 |
| 1032 instance = MyOtherMessage() |
| 1033 |
| 1034 self.assertRaisesWithRegexpMatch( |
| 1035 messages.EncodeError, |
| 1036 'Expected type MyMessage, got MyOtherMessage: <MyOtherMessage>', |
| 1037 HasMessage.field.value_to_message, instance) |
| 1038 |
| 1039 def testIntegerField_AllowLong(self): |
| 1040 """Test that the integer field allows for longs.""" |
| 1041 if six.PY2: |
| 1042 messages.IntegerField(10, default=long(10)) |
| 1043 |
| 1044 def testMessageFieldValidate_Initialized(self): |
| 1045 """Test validation on message field.""" |
| 1046 class MyMessage(messages.Message): |
| 1047 field1 = messages.IntegerField(1, required=True) |
| 1048 |
| 1049 field = messages.MessageField(MyMessage, 10) |
| 1050 |
| 1051 # Will validate messages where is_initialized() is False. |
| 1052 message = MyMessage() |
| 1053 field.validate(message) |
| 1054 message.field1 = 20 |
| 1055 field.validate(message) |
| 1056 |
| 1057 def testEnumField(self): |
| 1058 """Test the construction of enum fields.""" |
| 1059 self.assertRaises(messages.FieldDefinitionError, |
| 1060 messages.EnumField, |
| 1061 str, |
| 1062 10) |
| 1063 |
| 1064 self.assertRaises(messages.FieldDefinitionError, |
| 1065 messages.EnumField, |
| 1066 messages.Enum, |
| 1067 10) |
| 1068 |
| 1069 class Color(messages.Enum): |
| 1070 RED = 1 |
| 1071 GREEN = 2 |
| 1072 BLUE = 3 |
| 1073 |
| 1074 field = messages.EnumField(Color, 10) |
| 1075 self.assertEquals(Color, field.type) |
| 1076 |
| 1077 class Another(messages.Enum): |
| 1078 VALUE = 1 |
| 1079 |
| 1080 self.assertRaises(messages.InvalidDefaultError, |
| 1081 messages.EnumField, |
| 1082 Color, |
| 1083 10, |
| 1084 default=Another.VALUE) |
| 1085 |
| 1086 def testEnumField_ForwardReference(self): |
| 1087 """Test the construction of forward reference enum fields.""" |
| 1088 global MyMessage |
| 1089 global ForwardEnum |
| 1090 global ForwardMessage |
| 1091 try: |
| 1092 class MyMessage(messages.Message): |
| 1093 |
| 1094 forward = messages.EnumField('ForwardEnum', 1) |
| 1095 nested = messages.EnumField('ForwardMessage.NestedEnum', 2) |
| 1096 inner = messages.EnumField('Inner', 3) |
| 1097 |
| 1098 class Inner(messages.Enum): |
| 1099 pass |
| 1100 |
| 1101 class ForwardEnum(messages.Enum): |
| 1102 pass |
| 1103 |
| 1104 class ForwardMessage(messages.Message): |
| 1105 |
| 1106 class NestedEnum(messages.Enum): |
| 1107 pass |
| 1108 |
| 1109 self.assertEquals(ForwardEnum, |
| 1110 MyMessage.field_by_name('forward').type) |
| 1111 |
| 1112 self.assertEquals(ForwardMessage.NestedEnum, |
| 1113 MyMessage.field_by_name('nested').type) |
| 1114 |
| 1115 self.assertEquals(MyMessage.Inner, |
| 1116 MyMessage.field_by_name('inner').type) |
| 1117 finally: |
| 1118 try: |
| 1119 del MyMessage |
| 1120 del ForwardEnum |
| 1121 del ForwardMessage |
| 1122 except: # pylint:disable=bare-except |
| 1123 pass |
| 1124 |
| 1125 def testEnumField_WrongType(self): |
| 1126 """Test that forward referencing the wrong type raises an error.""" |
| 1127 global AMessage |
| 1128 try: |
| 1129 class AMessage(messages.Message): |
| 1130 pass |
| 1131 |
| 1132 class AnotherMessage(messages.Message): |
| 1133 |
| 1134 a_field = messages.EnumField('AMessage', 1) |
| 1135 |
| 1136 self.assertRaises(messages.FieldDefinitionError, |
| 1137 getattr, |
| 1138 AnotherMessage.field_by_name('a_field'), |
| 1139 'type') |
| 1140 finally: |
| 1141 del AMessage |
| 1142 |
| 1143 def testMessageDefinition(self): |
| 1144 """Test that message definition is set on fields.""" |
| 1145 class MyMessage(messages.Message): |
| 1146 |
| 1147 my_field = messages.StringField(1) |
| 1148 |
| 1149 self.assertEquals( |
| 1150 MyMessage, |
| 1151 MyMessage.field_by_name('my_field').message_definition()) |
| 1152 |
| 1153 def testNoneAssignment(self): |
| 1154 """Test that assigning None does not change comparison.""" |
| 1155 class MyMessage(messages.Message): |
| 1156 |
| 1157 my_field = messages.StringField(1) |
| 1158 |
| 1159 m1 = MyMessage() |
| 1160 m2 = MyMessage() |
| 1161 m2.my_field = None |
| 1162 self.assertEquals(m1, m2) |
| 1163 |
| 1164 def testNonAsciiStr(self): |
| 1165 """Test validation fails for non-ascii StringField values.""" |
| 1166 class Thing(messages.Message): |
| 1167 string_field = messages.StringField(2) |
| 1168 |
| 1169 thing = Thing() |
| 1170 self.assertRaisesWithRegexpMatch( |
| 1171 messages.ValidationError, |
| 1172 'Field string_field encountered non-ASCII string', |
| 1173 setattr, thing, 'string_field', test_util.BINARY) |
| 1174 |
| 1175 |
| 1176 class MessageTest(test_util.TestCase): |
| 1177 """Tests for message class.""" |
| 1178 |
| 1179 def CreateMessageClass(self): |
| 1180 """Creates a simple message class with 3 fields. |
| 1181 |
| 1182 Fields are defined in alphabetical order but with conflicting numeric |
| 1183 order. |
| 1184 """ |
| 1185 class ComplexMessage(messages.Message): |
| 1186 a3 = messages.IntegerField(3) |
| 1187 b1 = messages.StringField(1) |
| 1188 c2 = messages.StringField(2) |
| 1189 |
| 1190 return ComplexMessage |
| 1191 |
| 1192 def testSameNumbers(self): |
| 1193 """Test that cannot assign two fields with same numbers.""" |
| 1194 |
| 1195 def action(): |
| 1196 class BadMessage(messages.Message): |
| 1197 f1 = messages.IntegerField(1) |
| 1198 f2 = messages.IntegerField(1) |
| 1199 self.assertRaises(messages.DuplicateNumberError, |
| 1200 action) |
| 1201 |
| 1202 def testStrictAssignment(self): |
| 1203 """Tests that cannot assign to unknown or non-reserved attributes.""" |
| 1204 class SimpleMessage(messages.Message): |
| 1205 field = messages.IntegerField(1) |
| 1206 |
| 1207 simple_message = SimpleMessage() |
| 1208 self.assertRaises(AttributeError, |
| 1209 setattr, |
| 1210 simple_message, |
| 1211 'does_not_exist', |
| 1212 10) |
| 1213 |
| 1214 def testListAssignmentDoesNotCopy(self): |
| 1215 class SimpleMessage(messages.Message): |
| 1216 repeated = messages.IntegerField(1, repeated=True) |
| 1217 |
| 1218 message = SimpleMessage() |
| 1219 original = message.repeated |
| 1220 message.repeated = [] |
| 1221 self.assertFalse(original is message.repeated) |
| 1222 |
| 1223 def testValidate_Optional(self): |
| 1224 """Tests validation of optional fields.""" |
| 1225 class SimpleMessage(messages.Message): |
| 1226 non_required = messages.IntegerField(1) |
| 1227 |
| 1228 simple_message = SimpleMessage() |
| 1229 simple_message.check_initialized() |
| 1230 simple_message.non_required = 10 |
| 1231 simple_message.check_initialized() |
| 1232 |
| 1233 def testValidate_Required(self): |
| 1234 """Tests validation of required fields.""" |
| 1235 class SimpleMessage(messages.Message): |
| 1236 required = messages.IntegerField(1, required=True) |
| 1237 |
| 1238 simple_message = SimpleMessage() |
| 1239 self.assertRaises(messages.ValidationError, |
| 1240 simple_message.check_initialized) |
| 1241 simple_message.required = 10 |
| 1242 simple_message.check_initialized() |
| 1243 |
| 1244 def testValidate_Repeated(self): |
| 1245 """Tests validation of repeated fields.""" |
| 1246 class SimpleMessage(messages.Message): |
| 1247 repeated = messages.IntegerField(1, repeated=True) |
| 1248 |
| 1249 simple_message = SimpleMessage() |
| 1250 |
| 1251 # Check valid values. |
| 1252 for valid_value in [], [10], [10, 20], (), (10,), (10, 20): |
| 1253 simple_message.repeated = valid_value |
| 1254 simple_message.check_initialized() |
| 1255 |
| 1256 # Check cleared. |
| 1257 simple_message.repeated = [] |
| 1258 simple_message.check_initialized() |
| 1259 |
| 1260 # Check invalid values. |
| 1261 for invalid_value in 10, ['10', '20'], [None], (None,): |
| 1262 self.assertRaises( |
| 1263 messages.ValidationError, |
| 1264 setattr, simple_message, 'repeated', invalid_value) |
| 1265 |
| 1266 def testIsInitialized(self): |
| 1267 """Tests is_initialized.""" |
| 1268 class SimpleMessage(messages.Message): |
| 1269 required = messages.IntegerField(1, required=True) |
| 1270 |
| 1271 simple_message = SimpleMessage() |
| 1272 self.assertFalse(simple_message.is_initialized()) |
| 1273 |
| 1274 simple_message.required = 10 |
| 1275 |
| 1276 self.assertTrue(simple_message.is_initialized()) |
| 1277 |
| 1278 def testIsInitializedNestedField(self): |
| 1279 """Tests is_initialized for nested fields.""" |
| 1280 class SimpleMessage(messages.Message): |
| 1281 required = messages.IntegerField(1, required=True) |
| 1282 |
| 1283 class NestedMessage(messages.Message): |
| 1284 simple = messages.MessageField(SimpleMessage, 1) |
| 1285 |
| 1286 simple_message = SimpleMessage() |
| 1287 self.assertFalse(simple_message.is_initialized()) |
| 1288 nested_message = NestedMessage(simple=simple_message) |
| 1289 self.assertFalse(nested_message.is_initialized()) |
| 1290 |
| 1291 simple_message.required = 10 |
| 1292 |
| 1293 self.assertTrue(simple_message.is_initialized()) |
| 1294 self.assertTrue(nested_message.is_initialized()) |
| 1295 |
| 1296 def testInitializeNestedFieldFromDict(self): |
| 1297 """Tests initializing nested fields from dict.""" |
| 1298 class SimpleMessage(messages.Message): |
| 1299 required = messages.IntegerField(1, required=True) |
| 1300 |
| 1301 class NestedMessage(messages.Message): |
| 1302 simple = messages.MessageField(SimpleMessage, 1) |
| 1303 |
| 1304 class RepeatedMessage(messages.Message): |
| 1305 simple = messages.MessageField(SimpleMessage, 1, repeated=True) |
| 1306 |
| 1307 nested_message1 = NestedMessage(simple={'required': 10}) |
| 1308 self.assertTrue(nested_message1.is_initialized()) |
| 1309 self.assertTrue(nested_message1.simple.is_initialized()) |
| 1310 |
| 1311 nested_message2 = NestedMessage() |
| 1312 nested_message2.simple = {'required': 10} |
| 1313 self.assertTrue(nested_message2.is_initialized()) |
| 1314 self.assertTrue(nested_message2.simple.is_initialized()) |
| 1315 |
| 1316 repeated_values = [{}, {'required': 10}, SimpleMessage(required=20)] |
| 1317 |
| 1318 repeated_message1 = RepeatedMessage(simple=repeated_values) |
| 1319 self.assertEquals(3, len(repeated_message1.simple)) |
| 1320 self.assertFalse(repeated_message1.is_initialized()) |
| 1321 |
| 1322 repeated_message1.simple[0].required = 0 |
| 1323 self.assertTrue(repeated_message1.is_initialized()) |
| 1324 |
| 1325 repeated_message2 = RepeatedMessage() |
| 1326 repeated_message2.simple = repeated_values |
| 1327 self.assertEquals(3, len(repeated_message2.simple)) |
| 1328 self.assertFalse(repeated_message2.is_initialized()) |
| 1329 |
| 1330 repeated_message2.simple[0].required = 0 |
| 1331 self.assertTrue(repeated_message2.is_initialized()) |
| 1332 |
| 1333 def testNestedMethodsNotAllowed(self): |
| 1334 """Test that method definitions on Message classes are not allowed.""" |
| 1335 def action(): |
| 1336 class WithMethods(messages.Message): |
| 1337 |
| 1338 def not_allowed(self): |
| 1339 pass |
| 1340 |
| 1341 self.assertRaises(messages.MessageDefinitionError, |
| 1342 action) |
| 1343 |
| 1344 def testNestedAttributesNotAllowed(self): |
| 1345 """Test attribute assignment on Message classes is not allowed.""" |
| 1346 def int_attribute(): |
| 1347 class WithMethods(messages.Message): |
| 1348 not_allowed = 1 |
| 1349 |
| 1350 def string_attribute(): |
| 1351 class WithMethods(messages.Message): |
| 1352 not_allowed = 'not allowed' |
| 1353 |
| 1354 def enum_attribute(): |
| 1355 class WithMethods(messages.Message): |
| 1356 not_allowed = Color.RED |
| 1357 |
| 1358 for action in (int_attribute, string_attribute, enum_attribute): |
| 1359 self.assertRaises(messages.MessageDefinitionError, |
| 1360 action) |
| 1361 |
| 1362 def testNameIsSetOnFields(self): |
| 1363 """Make sure name is set on fields after Message class init.""" |
| 1364 class HasNamedFields(messages.Message): |
| 1365 field = messages.StringField(1) |
| 1366 |
| 1367 self.assertEquals('field', HasNamedFields.field_by_number(1).name) |
| 1368 |
| 1369 def testSubclassingMessageDisallowed(self): |
| 1370 """Not permitted to create sub-classes of message classes.""" |
| 1371 class SuperClass(messages.Message): |
| 1372 pass |
| 1373 |
| 1374 def action(): |
| 1375 class SubClass(SuperClass): |
| 1376 pass |
| 1377 |
| 1378 self.assertRaises(messages.MessageDefinitionError, |
| 1379 action) |
| 1380 |
| 1381 def testAllFields(self): |
| 1382 """Test all_fields method.""" |
| 1383 ComplexMessage = self.CreateMessageClass() |
| 1384 fields = list(ComplexMessage.all_fields()) |
| 1385 |
| 1386 # Order does not matter, so sort now. |
| 1387 fields = sorted(fields, key=lambda f: f.name) |
| 1388 |
| 1389 self.assertEquals(3, len(fields)) |
| 1390 self.assertEquals('a3', fields[0].name) |
| 1391 self.assertEquals('b1', fields[1].name) |
| 1392 self.assertEquals('c2', fields[2].name) |
| 1393 |
| 1394 def testFieldByName(self): |
| 1395 """Test getting field by name.""" |
| 1396 ComplexMessage = self.CreateMessageClass() |
| 1397 |
| 1398 self.assertEquals(3, ComplexMessage.field_by_name('a3').number) |
| 1399 self.assertEquals(1, ComplexMessage.field_by_name('b1').number) |
| 1400 self.assertEquals(2, ComplexMessage.field_by_name('c2').number) |
| 1401 |
| 1402 self.assertRaises(KeyError, |
| 1403 ComplexMessage.field_by_name, |
| 1404 'unknown') |
| 1405 |
| 1406 def testFieldByNumber(self): |
| 1407 """Test getting field by number.""" |
| 1408 ComplexMessage = self.CreateMessageClass() |
| 1409 |
| 1410 self.assertEquals('a3', ComplexMessage.field_by_number(3).name) |
| 1411 self.assertEquals('b1', ComplexMessage.field_by_number(1).name) |
| 1412 self.assertEquals('c2', ComplexMessage.field_by_number(2).name) |
| 1413 |
| 1414 self.assertRaises(KeyError, |
| 1415 ComplexMessage.field_by_number, |
| 1416 4) |
| 1417 |
| 1418 def testGetAssignedValue(self): |
| 1419 """Test getting the assigned value of a field.""" |
| 1420 class SomeMessage(messages.Message): |
| 1421 a_value = messages.StringField(1, default=u'a default') |
| 1422 |
| 1423 message = SomeMessage() |
| 1424 self.assertEquals(None, message.get_assigned_value('a_value')) |
| 1425 |
| 1426 message.a_value = u'a string' |
| 1427 self.assertEquals(u'a string', message.get_assigned_value('a_value')) |
| 1428 |
| 1429 message.a_value = u'a default' |
| 1430 self.assertEquals(u'a default', message.get_assigned_value('a_value')) |
| 1431 |
| 1432 self.assertRaisesWithRegexpMatch( |
| 1433 AttributeError, |
| 1434 'Message SomeMessage has no field no_such_field', |
| 1435 message.get_assigned_value, |
| 1436 'no_such_field') |
| 1437 |
| 1438 def testReset(self): |
| 1439 """Test resetting a field value.""" |
| 1440 class SomeMessage(messages.Message): |
| 1441 a_value = messages.StringField(1, default=u'a default') |
| 1442 repeated = messages.IntegerField(2, repeated=True) |
| 1443 |
| 1444 message = SomeMessage() |
| 1445 |
| 1446 self.assertRaises(AttributeError, message.reset, 'unknown') |
| 1447 |
| 1448 self.assertEquals(u'a default', message.a_value) |
| 1449 message.reset('a_value') |
| 1450 self.assertEquals(u'a default', message.a_value) |
| 1451 |
| 1452 message.a_value = u'a new value' |
| 1453 self.assertEquals(u'a new value', message.a_value) |
| 1454 message.reset('a_value') |
| 1455 self.assertEquals(u'a default', message.a_value) |
| 1456 |
| 1457 message.repeated = [1, 2, 3] |
| 1458 self.assertEquals([1, 2, 3], message.repeated) |
| 1459 saved = message.repeated |
| 1460 message.reset('repeated') |
| 1461 self.assertEquals([], message.repeated) |
| 1462 self.assertIsInstance(message.repeated, messages.FieldList) |
| 1463 self.assertEquals([1, 2, 3], saved) |
| 1464 |
| 1465 def testAllowNestedEnums(self): |
| 1466 """Test allowing nested enums in a message definition.""" |
| 1467 class Trade(messages.Message): |
| 1468 |
| 1469 class Duration(messages.Enum): |
| 1470 GTC = 1 |
| 1471 DAY = 2 |
| 1472 |
| 1473 class Currency(messages.Enum): |
| 1474 USD = 1 |
| 1475 GBP = 2 |
| 1476 INR = 3 |
| 1477 |
| 1478 # Sorted by name order seems to be the only feasible option. |
| 1479 self.assertEquals(['Currency', 'Duration'], Trade.__enums__) |
| 1480 |
| 1481 # Message definition will now be set on Enumerated objects. |
| 1482 self.assertEquals(Trade, Trade.Duration.message_definition()) |
| 1483 |
| 1484 def testAllowNestedMessages(self): |
| 1485 """Test allowing nested messages in a message definition.""" |
| 1486 class Trade(messages.Message): |
| 1487 |
| 1488 class Lot(messages.Message): |
| 1489 pass |
| 1490 |
| 1491 class Agent(messages.Message): |
| 1492 pass |
| 1493 |
| 1494 # Sorted by name order seems to be the only feasible option. |
| 1495 self.assertEquals(['Agent', 'Lot'], Trade.__messages__) |
| 1496 self.assertEquals(Trade, Trade.Agent.message_definition()) |
| 1497 self.assertEquals(Trade, Trade.Lot.message_definition()) |
| 1498 |
| 1499 # But not Message itself. |
| 1500 def action(): |
| 1501 class Trade(messages.Message): |
| 1502 NiceTry = messages.Message |
| 1503 self.assertRaises(messages.MessageDefinitionError, action) |
| 1504 |
| 1505 def testDisallowClassAssignments(self): |
| 1506 """Test setting class attributes may not happen.""" |
| 1507 class MyMessage(messages.Message): |
| 1508 pass |
| 1509 |
| 1510 self.assertRaises(AttributeError, |
| 1511 setattr, |
| 1512 MyMessage, |
| 1513 'x', |
| 1514 'do not assign') |
| 1515 |
| 1516 def testEquality(self): |
| 1517 """Test message class equality.""" |
| 1518 # Comparison against enums must work. |
| 1519 class MyEnum(messages.Enum): |
| 1520 val1 = 1 |
| 1521 val2 = 2 |
| 1522 |
| 1523 # Comparisons against nested messages must work. |
| 1524 class AnotherMessage(messages.Message): |
| 1525 string = messages.StringField(1) |
| 1526 |
| 1527 class MyMessage(messages.Message): |
| 1528 field1 = messages.IntegerField(1) |
| 1529 field2 = messages.EnumField(MyEnum, 2) |
| 1530 field3 = messages.MessageField(AnotherMessage, 3) |
| 1531 |
| 1532 message1 = MyMessage() |
| 1533 |
| 1534 self.assertNotEquals('hi', message1) |
| 1535 self.assertNotEquals(AnotherMessage(), message1) |
| 1536 self.assertEquals(message1, message1) |
| 1537 |
| 1538 message2 = MyMessage() |
| 1539 |
| 1540 self.assertEquals(message1, message2) |
| 1541 |
| 1542 message1.field1 = 10 |
| 1543 self.assertNotEquals(message1, message2) |
| 1544 |
| 1545 message2.field1 = 20 |
| 1546 self.assertNotEquals(message1, message2) |
| 1547 |
| 1548 message2.field1 = 10 |
| 1549 self.assertEquals(message1, message2) |
| 1550 |
| 1551 message1.field2 = MyEnum.val1 |
| 1552 self.assertNotEquals(message1, message2) |
| 1553 |
| 1554 message2.field2 = MyEnum.val2 |
| 1555 self.assertNotEquals(message1, message2) |
| 1556 |
| 1557 message2.field2 = MyEnum.val1 |
| 1558 self.assertEquals(message1, message2) |
| 1559 |
| 1560 message1.field3 = AnotherMessage() |
| 1561 message1.field3.string = 'value1' |
| 1562 self.assertNotEquals(message1, message2) |
| 1563 |
| 1564 message2.field3 = AnotherMessage() |
| 1565 message2.field3.string = 'value2' |
| 1566 self.assertNotEquals(message1, message2) |
| 1567 |
| 1568 message2.field3.string = 'value1' |
| 1569 self.assertEquals(message1, message2) |
| 1570 |
| 1571 def testEqualityWithUnknowns(self): |
| 1572 """Test message class equality with unknown fields.""" |
| 1573 |
| 1574 class MyMessage(messages.Message): |
| 1575 field1 = messages.IntegerField(1) |
| 1576 |
| 1577 message1 = MyMessage() |
| 1578 message2 = MyMessage() |
| 1579 self.assertEquals(message1, message2) |
| 1580 message1.set_unrecognized_field('unknown1', 'value1', |
| 1581 messages.Variant.STRING) |
| 1582 self.assertEquals(message1, message2) |
| 1583 |
| 1584 message1.set_unrecognized_field('unknown2', ['asdf', 3], |
| 1585 messages.Variant.STRING) |
| 1586 message1.set_unrecognized_field('unknown3', 4.7, |
| 1587 messages.Variant.DOUBLE) |
| 1588 self.assertEquals(message1, message2) |
| 1589 |
| 1590 def testUnrecognizedFieldInvalidVariant(self): |
| 1591 class MyMessage(messages.Message): |
| 1592 field1 = messages.IntegerField(1) |
| 1593 |
| 1594 message1 = MyMessage() |
| 1595 self.assertRaises( |
| 1596 TypeError, message1.set_unrecognized_field, 'unknown4', |
| 1597 {'unhandled': 'type'}, None) |
| 1598 self.assertRaises( |
| 1599 TypeError, message1.set_unrecognized_field, 'unknown4', |
| 1600 {'unhandled': 'type'}, 123) |
| 1601 |
| 1602 def testRepr(self): |
| 1603 """Test represtation of Message object.""" |
| 1604 class MyMessage(messages.Message): |
| 1605 integer_value = messages.IntegerField(1) |
| 1606 string_value = messages.StringField(2) |
| 1607 unassigned = messages.StringField(3) |
| 1608 unassigned_with_default = messages.StringField( |
| 1609 4, default=u'a default') |
| 1610 |
| 1611 my_message = MyMessage() |
| 1612 my_message.integer_value = 42 |
| 1613 my_message.string_value = u'A string' |
| 1614 |
| 1615 pat = re.compile(r"<MyMessage\n integer_value: 42\n" |
| 1616 " string_value: [u]?'A string'>") |
| 1617 self.assertTrue(pat.match(repr(my_message)) is not None) |
| 1618 |
| 1619 def testValidation(self): |
| 1620 """Test validation of message values.""" |
| 1621 # Test optional. |
| 1622 class SubMessage(messages.Message): |
| 1623 pass |
| 1624 |
| 1625 class Message(messages.Message): |
| 1626 val = messages.MessageField(SubMessage, 1) |
| 1627 |
| 1628 message = Message() |
| 1629 |
| 1630 message_field = messages.MessageField(Message, 1) |
| 1631 message_field.validate(message) |
| 1632 message.val = SubMessage() |
| 1633 message_field.validate(message) |
| 1634 self.assertRaises(messages.ValidationError, |
| 1635 setattr, message, 'val', [SubMessage()]) |
| 1636 |
| 1637 # Test required. |
| 1638 class Message(messages.Message): |
| 1639 val = messages.MessageField(SubMessage, 1, required=True) |
| 1640 |
| 1641 message = Message() |
| 1642 |
| 1643 message_field = messages.MessageField(Message, 1) |
| 1644 message_field.validate(message) |
| 1645 message.val = SubMessage() |
| 1646 message_field.validate(message) |
| 1647 self.assertRaises(messages.ValidationError, |
| 1648 setattr, message, 'val', [SubMessage()]) |
| 1649 |
| 1650 # Test repeated. |
| 1651 class Message(messages.Message): |
| 1652 val = messages.MessageField(SubMessage, 1, repeated=True) |
| 1653 |
| 1654 message = Message() |
| 1655 |
| 1656 message_field = messages.MessageField(Message, 1) |
| 1657 message_field.validate(message) |
| 1658 self.assertRaisesWithRegexpMatch( |
| 1659 messages.ValidationError, |
| 1660 "Field val is repeated. Found: <SubMessage>", |
| 1661 setattr, message, 'val', SubMessage()) |
| 1662 # pylint: disable=redefined-variable-type |
| 1663 message.val = [SubMessage()] |
| 1664 message_field.validate(message) |
| 1665 |
| 1666 def testDefinitionName(self): |
| 1667 """Test message name.""" |
| 1668 class MyMessage(messages.Message): |
| 1669 pass |
| 1670 |
| 1671 module_name = test_util.get_module_name(FieldTest) |
| 1672 self.assertEquals('%s.MyMessage' % module_name, |
| 1673 MyMessage.definition_name()) |
| 1674 self.assertEquals(module_name, MyMessage.outer_definition_name()) |
| 1675 self.assertEquals(module_name, MyMessage.definition_package()) |
| 1676 |
| 1677 self.assertEquals(six.text_type, type(MyMessage.definition_name())) |
| 1678 self.assertEquals(six.text_type, type( |
| 1679 MyMessage.outer_definition_name())) |
| 1680 self.assertEquals(six.text_type, type(MyMessage.definition_package())) |
| 1681 |
| 1682 def testDefinitionName_OverrideModule(self): |
| 1683 """Test message module is overriden by module package name.""" |
| 1684 class MyMessage(messages.Message): |
| 1685 pass |
| 1686 |
| 1687 global package |
| 1688 package = 'my.package' |
| 1689 |
| 1690 try: |
| 1691 self.assertEquals('my.package.MyMessage', |
| 1692 MyMessage.definition_name()) |
| 1693 self.assertEquals('my.package', MyMessage.outer_definition_name()) |
| 1694 self.assertEquals('my.package', MyMessage.definition_package()) |
| 1695 |
| 1696 self.assertEquals(six.text_type, type(MyMessage.definition_name())) |
| 1697 self.assertEquals(six.text_type, type( |
| 1698 MyMessage.outer_definition_name())) |
| 1699 self.assertEquals(six.text_type, type( |
| 1700 MyMessage.definition_package())) |
| 1701 finally: |
| 1702 del package |
| 1703 |
| 1704 def testDefinitionName_NoModule(self): |
| 1705 """Test what happens when there is no module for message.""" |
| 1706 class MyMessage(messages.Message): |
| 1707 pass |
| 1708 |
| 1709 original_modules = sys.modules |
| 1710 sys.modules = dict(sys.modules) |
| 1711 try: |
| 1712 del sys.modules[__name__] |
| 1713 self.assertEquals('MyMessage', MyMessage.definition_name()) |
| 1714 self.assertEquals(None, MyMessage.outer_definition_name()) |
| 1715 self.assertEquals(None, MyMessage.definition_package()) |
| 1716 |
| 1717 self.assertEquals(six.text_type, type(MyMessage.definition_name())) |
| 1718 finally: |
| 1719 sys.modules = original_modules |
| 1720 |
| 1721 def testDefinitionName_Nested(self): |
| 1722 """Test nested message names.""" |
| 1723 class MyMessage(messages.Message): |
| 1724 |
| 1725 class NestedMessage(messages.Message): |
| 1726 |
| 1727 class NestedMessage(messages.Message): |
| 1728 |
| 1729 pass |
| 1730 |
| 1731 module_name = test_util.get_module_name(MessageTest) |
| 1732 self.assertEquals('%s.MyMessage.NestedMessage' % module_name, |
| 1733 MyMessage.NestedMessage.definition_name()) |
| 1734 self.assertEquals('%s.MyMessage' % module_name, |
| 1735 MyMessage.NestedMessage.outer_definition_name()) |
| 1736 self.assertEquals(module_name, |
| 1737 MyMessage.NestedMessage.definition_package()) |
| 1738 |
| 1739 self.assertEquals( |
| 1740 '%s.MyMessage.NestedMessage.NestedMessage' % module_name, |
| 1741 MyMessage.NestedMessage.NestedMessage.definition_name()) |
| 1742 self.assertEquals( |
| 1743 '%s.MyMessage.NestedMessage' % module_name, |
| 1744 MyMessage.NestedMessage.NestedMessage.outer_definition_name()) |
| 1745 self.assertEquals( |
| 1746 module_name, |
| 1747 MyMessage.NestedMessage.NestedMessage.definition_package()) |
| 1748 |
| 1749 def testMessageDefinition(self): |
| 1750 """Test that enumeration knows its enclosing message definition.""" |
| 1751 class OuterMessage(messages.Message): |
| 1752 |
| 1753 class InnerMessage(messages.Message): |
| 1754 pass |
| 1755 |
| 1756 self.assertEquals(None, OuterMessage.message_definition()) |
| 1757 self.assertEquals(OuterMessage, |
| 1758 OuterMessage.InnerMessage.message_definition()) |
| 1759 |
| 1760 def testConstructorKwargs(self): |
| 1761 """Test kwargs via constructor.""" |
| 1762 class SomeMessage(messages.Message): |
| 1763 name = messages.StringField(1) |
| 1764 number = messages.IntegerField(2) |
| 1765 |
| 1766 expected = SomeMessage() |
| 1767 expected.name = 'my name' |
| 1768 expected.number = 200 |
| 1769 self.assertEquals(expected, SomeMessage(name='my name', number=200)) |
| 1770 |
| 1771 def testConstructorNotAField(self): |
| 1772 """Test kwargs via constructor with wrong names.""" |
| 1773 class SomeMessage(messages.Message): |
| 1774 pass |
| 1775 |
| 1776 self.assertRaisesWithRegexpMatch( |
| 1777 AttributeError, |
| 1778 ('May not assign arbitrary value does_not_exist to message ' |
| 1779 'SomeMessage'), |
| 1780 SomeMessage, |
| 1781 does_not_exist=10) |
| 1782 |
| 1783 def testGetUnsetRepeatedValue(self): |
| 1784 class SomeMessage(messages.Message): |
| 1785 repeated = messages.IntegerField(1, repeated=True) |
| 1786 |
| 1787 instance = SomeMessage() |
| 1788 self.assertEquals([], instance.repeated) |
| 1789 self.assertTrue(isinstance(instance.repeated, messages.FieldList)) |
| 1790 |
| 1791 def testCompareAutoInitializedRepeatedFields(self): |
| 1792 class SomeMessage(messages.Message): |
| 1793 repeated = messages.IntegerField(1, repeated=True) |
| 1794 |
| 1795 message1 = SomeMessage(repeated=[]) |
| 1796 message2 = SomeMessage() |
| 1797 self.assertEquals(message1, message2) |
| 1798 |
| 1799 def testUnknownValues(self): |
| 1800 """Test message class equality with unknown fields.""" |
| 1801 class MyMessage(messages.Message): |
| 1802 field1 = messages.IntegerField(1) |
| 1803 |
| 1804 message = MyMessage() |
| 1805 self.assertEquals([], message.all_unrecognized_fields()) |
| 1806 self.assertEquals((None, None), |
| 1807 message.get_unrecognized_field_info('doesntexist')) |
| 1808 self.assertEquals((None, None), |
| 1809 message.get_unrecognized_field_info( |
| 1810 'doesntexist', None, None)) |
| 1811 self.assertEquals(('defaultvalue', 'defaultwire'), |
| 1812 message.get_unrecognized_field_info( |
| 1813 'doesntexist', 'defaultvalue', 'defaultwire')) |
| 1814 self.assertEquals((3, None), |
| 1815 message.get_unrecognized_field_info( |
| 1816 'doesntexist', value_default=3)) |
| 1817 |
| 1818 message.set_unrecognized_field('exists', 9.5, messages.Variant.DOUBLE) |
| 1819 self.assertEquals(1, len(message.all_unrecognized_fields())) |
| 1820 self.assertTrue('exists' in message.all_unrecognized_fields()) |
| 1821 self.assertEquals((9.5, messages.Variant.DOUBLE), |
| 1822 message.get_unrecognized_field_info('exists')) |
| 1823 self.assertEquals((9.5, messages.Variant.DOUBLE), |
| 1824 message.get_unrecognized_field_info('exists', 'type', |
| 1825 1234)) |
| 1826 self.assertEquals( |
| 1827 (1234, None), |
| 1828 message.get_unrecognized_field_info('doesntexist', 1234)) |
| 1829 |
| 1830 message.set_unrecognized_field( |
| 1831 'another', 'value', messages.Variant.STRING) |
| 1832 self.assertEquals(2, len(message.all_unrecognized_fields())) |
| 1833 self.assertTrue('exists' in message.all_unrecognized_fields()) |
| 1834 self.assertTrue('another' in message.all_unrecognized_fields()) |
| 1835 self.assertEquals((9.5, messages.Variant.DOUBLE), |
| 1836 message.get_unrecognized_field_info('exists')) |
| 1837 self.assertEquals(('value', messages.Variant.STRING), |
| 1838 message.get_unrecognized_field_info('another')) |
| 1839 |
| 1840 message.set_unrecognized_field('typetest1', ['list', 0, ('test',)], |
| 1841 messages.Variant.STRING) |
| 1842 self.assertEquals((['list', 0, ('test',)], messages.Variant.STRING), |
| 1843 message.get_unrecognized_field_info('typetest1')) |
| 1844 message.set_unrecognized_field( |
| 1845 'typetest2', '', messages.Variant.STRING) |
| 1846 self.assertEquals(('', messages.Variant.STRING), |
| 1847 message.get_unrecognized_field_info('typetest2')) |
| 1848 |
| 1849 def testPickle(self): |
| 1850 """Testing pickling and unpickling of Message instances.""" |
| 1851 global MyEnum |
| 1852 global AnotherMessage |
| 1853 global MyMessage |
| 1854 |
| 1855 class MyEnum(messages.Enum): |
| 1856 val1 = 1 |
| 1857 val2 = 2 |
| 1858 |
| 1859 class AnotherMessage(messages.Message): |
| 1860 string = messages.StringField(1, repeated=True) |
| 1861 |
| 1862 class MyMessage(messages.Message): |
| 1863 field1 = messages.IntegerField(1) |
| 1864 field2 = messages.EnumField(MyEnum, 2) |
| 1865 field3 = messages.MessageField(AnotherMessage, 3) |
| 1866 |
| 1867 message = MyMessage(field1=1, field2=MyEnum.val2, |
| 1868 field3=AnotherMessage(string=['a', 'b', 'c'])) |
| 1869 message.set_unrecognized_field( |
| 1870 'exists', 'value', messages.Variant.STRING) |
| 1871 message.set_unrecognized_field('repeated', ['list', 0, ('test',)], |
| 1872 messages.Variant.STRING) |
| 1873 unpickled = pickle.loads(pickle.dumps(message)) |
| 1874 self.assertEquals(message, unpickled) |
| 1875 self.assertTrue(AnotherMessage.string is unpickled.field3.string.field) |
| 1876 self.assertTrue('exists' in message.all_unrecognized_fields()) |
| 1877 self.assertEquals(('value', messages.Variant.STRING), |
| 1878 message.get_unrecognized_field_info('exists')) |
| 1879 self.assertEquals((['list', 0, ('test',)], messages.Variant.STRING), |
| 1880 message.get_unrecognized_field_info('repeated')) |
| 1881 |
| 1882 |
| 1883 class FindDefinitionTest(test_util.TestCase): |
| 1884 """Test finding definitions relative to various definitions and modules.""" |
| 1885 |
| 1886 def setUp(self): |
| 1887 """Set up module-space. Starts off empty.""" |
| 1888 self.modules = {} |
| 1889 |
| 1890 def DefineModule(self, name): |
| 1891 """Define a module and its parents in module space. |
| 1892 |
| 1893 Modules that are already defined in self.modules are not re-created. |
| 1894 |
| 1895 Args: |
| 1896 name: Fully qualified name of modules to create. |
| 1897 |
| 1898 Returns: |
| 1899 Deepest nested module. For example: |
| 1900 |
| 1901 DefineModule('a.b.c') # Returns c. |
| 1902 """ |
| 1903 name_path = name.split('.') |
| 1904 full_path = [] |
| 1905 for node in name_path: |
| 1906 full_path.append(node) |
| 1907 full_name = '.'.join(full_path) |
| 1908 self.modules.setdefault(full_name, types.ModuleType(full_name)) |
| 1909 return self.modules[name] |
| 1910 |
| 1911 def DefineMessage(self, module, name, children=None, add_to_module=True): |
| 1912 """Define a new Message class in the context of a module. |
| 1913 |
| 1914 Used for easily describing complex Message hierarchy. Message |
| 1915 is defined including all child definitions. |
| 1916 |
| 1917 Args: |
| 1918 module: Fully qualified name of module to place Message class in. |
| 1919 name: Name of Message to define within module. |
| 1920 children: Define any level of nesting of children |
| 1921 definitions. To define a message, map the name to another |
| 1922 dictionary. The dictionary can itself contain additional |
| 1923 definitions, and so on. To map to an Enum, define the Enum |
| 1924 class separately and map it by name. |
| 1925 add_to_module: If True, new Message class is added to |
| 1926 module. If False, new Message is not added. |
| 1927 |
| 1928 """ |
| 1929 children = children or {} |
| 1930 # Make sure module exists. |
| 1931 module_instance = self.DefineModule(module) |
| 1932 |
| 1933 # Recursively define all child messages. |
| 1934 for attribute, value in children.items(): |
| 1935 if isinstance(value, dict): |
| 1936 children[attribute] = self.DefineMessage( |
| 1937 module, attribute, value, False) |
| 1938 |
| 1939 # Override default __module__ variable. |
| 1940 children['__module__'] = module |
| 1941 |
| 1942 # Instantiate and possibly add to module. |
| 1943 message_class = type(name, (messages.Message,), dict(children)) |
| 1944 if add_to_module: |
| 1945 setattr(module_instance, name, message_class) |
| 1946 return message_class |
| 1947 |
| 1948 # pylint:disable=unused-argument |
| 1949 # pylint:disable=redefined-builtin |
| 1950 def Importer(self, module, globals='', locals='', fromlist=None): |
| 1951 """Importer function. |
| 1952 |
| 1953 Acts like __import__. Only loads modules from self.modules. |
| 1954 Does not try to load real modules defined elsewhere. Does not |
| 1955 try to handle relative imports. |
| 1956 |
| 1957 Args: |
| 1958 module: Fully qualified name of module to load from self.modules. |
| 1959 |
| 1960 """ |
| 1961 if fromlist is None: |
| 1962 module = module.split('.')[0] |
| 1963 try: |
| 1964 return self.modules[module] |
| 1965 except KeyError: |
| 1966 raise ImportError() |
| 1967 # pylint:disable=unused-argument |
| 1968 |
| 1969 def testNoSuchModule(self): |
| 1970 """Test searching for definitions that do no exist.""" |
| 1971 self.assertRaises(messages.DefinitionNotFoundError, |
| 1972 messages.find_definition, |
| 1973 'does.not.exist', |
| 1974 importer=self.Importer) |
| 1975 |
| 1976 def testRefersToModule(self): |
| 1977 """Test that referring to a module does not return that module.""" |
| 1978 self.DefineModule('i.am.a.module') |
| 1979 self.assertRaises(messages.DefinitionNotFoundError, |
| 1980 messages.find_definition, |
| 1981 'i.am.a.module', |
| 1982 importer=self.Importer) |
| 1983 |
| 1984 def testNoDefinition(self): |
| 1985 """Test not finding a definition in an existing module.""" |
| 1986 self.DefineModule('i.am.a.module') |
| 1987 self.assertRaises(messages.DefinitionNotFoundError, |
| 1988 messages.find_definition, |
| 1989 'i.am.a.module.MyMessage', |
| 1990 importer=self.Importer) |
| 1991 |
| 1992 def testNotADefinition(self): |
| 1993 """Test trying to fetch something that is not a definition.""" |
| 1994 module = self.DefineModule('i.am.a.module') |
| 1995 setattr(module, 'A', 'a string') |
| 1996 self.assertRaises(messages.DefinitionNotFoundError, |
| 1997 messages.find_definition, |
| 1998 'i.am.a.module.A', |
| 1999 importer=self.Importer) |
| 2000 |
| 2001 def testGlobalFind(self): |
| 2002 """Test finding definitions from fully qualified module names.""" |
| 2003 A = self.DefineMessage('a.b.c', 'A', {}) |
| 2004 self.assertEquals(A, messages.find_definition('a.b.c.A', |
| 2005 importer=self.Importer)) |
| 2006 B = self.DefineMessage('a.b.c', 'B', {'C': {}}) |
| 2007 self.assertEquals( |
| 2008 B.C, |
| 2009 messages.find_definition('a.b.c.B.C', importer=self.Importer)) |
| 2010 |
| 2011 def testRelativeToModule(self): |
| 2012 """Test finding definitions relative to modules.""" |
| 2013 # Define modules. |
| 2014 a = self.DefineModule('a') |
| 2015 b = self.DefineModule('a.b') |
| 2016 c = self.DefineModule('a.b.c') |
| 2017 |
| 2018 # Define messages. |
| 2019 A = self.DefineMessage('a', 'A') |
| 2020 B = self.DefineMessage('a.b', 'B') |
| 2021 C = self.DefineMessage('a.b.c', 'C') |
| 2022 D = self.DefineMessage('a.b.d', 'D') |
| 2023 |
| 2024 # Find A, B, C and D relative to a. |
| 2025 self.assertEquals(A, messages.find_definition( |
| 2026 'A', a, importer=self.Importer)) |
| 2027 self.assertEquals(B, messages.find_definition( |
| 2028 'b.B', a, importer=self.Importer)) |
| 2029 self.assertEquals(C, messages.find_definition( |
| 2030 'b.c.C', a, importer=self.Importer)) |
| 2031 self.assertEquals(D, messages.find_definition( |
| 2032 'b.d.D', a, importer=self.Importer)) |
| 2033 |
| 2034 # Find A, B, C and D relative to b. |
| 2035 self.assertEquals(A, messages.find_definition( |
| 2036 'A', b, importer=self.Importer)) |
| 2037 self.assertEquals(B, messages.find_definition( |
| 2038 'B', b, importer=self.Importer)) |
| 2039 self.assertEquals(C, messages.find_definition( |
| 2040 'c.C', b, importer=self.Importer)) |
| 2041 self.assertEquals(D, messages.find_definition( |
| 2042 'd.D', b, importer=self.Importer)) |
| 2043 |
| 2044 # Find A, B, C and D relative to c. Module d is the same case as c. |
| 2045 self.assertEquals(A, messages.find_definition( |
| 2046 'A', c, importer=self.Importer)) |
| 2047 self.assertEquals(B, messages.find_definition( |
| 2048 'B', c, importer=self.Importer)) |
| 2049 self.assertEquals(C, messages.find_definition( |
| 2050 'C', c, importer=self.Importer)) |
| 2051 self.assertEquals(D, messages.find_definition( |
| 2052 'd.D', c, importer=self.Importer)) |
| 2053 |
| 2054 def testRelativeToMessages(self): |
| 2055 """Test finding definitions relative to Message definitions.""" |
| 2056 A = self.DefineMessage('a.b', 'A', {'B': {'C': {}, 'D': {}}}) |
| 2057 B = A.B |
| 2058 C = A.B.C |
| 2059 D = A.B.D |
| 2060 |
| 2061 # Find relative to A. |
| 2062 self.assertEquals(A, messages.find_definition( |
| 2063 'A', A, importer=self.Importer)) |
| 2064 self.assertEquals(B, messages.find_definition( |
| 2065 'B', A, importer=self.Importer)) |
| 2066 self.assertEquals(C, messages.find_definition( |
| 2067 'B.C', A, importer=self.Importer)) |
| 2068 self.assertEquals(D, messages.find_definition( |
| 2069 'B.D', A, importer=self.Importer)) |
| 2070 |
| 2071 # Find relative to B. |
| 2072 self.assertEquals(A, messages.find_definition( |
| 2073 'A', B, importer=self.Importer)) |
| 2074 self.assertEquals(B, messages.find_definition( |
| 2075 'B', B, importer=self.Importer)) |
| 2076 self.assertEquals(C, messages.find_definition( |
| 2077 'C', B, importer=self.Importer)) |
| 2078 self.assertEquals(D, messages.find_definition( |
| 2079 'D', B, importer=self.Importer)) |
| 2080 |
| 2081 # Find relative to C. |
| 2082 self.assertEquals(A, messages.find_definition( |
| 2083 'A', C, importer=self.Importer)) |
| 2084 self.assertEquals(B, messages.find_definition( |
| 2085 'B', C, importer=self.Importer)) |
| 2086 self.assertEquals(C, messages.find_definition( |
| 2087 'C', C, importer=self.Importer)) |
| 2088 self.assertEquals(D, messages.find_definition( |
| 2089 'D', C, importer=self.Importer)) |
| 2090 |
| 2091 # Find relative to C searching from c. |
| 2092 self.assertEquals(A, messages.find_definition( |
| 2093 'b.A', C, importer=self.Importer)) |
| 2094 self.assertEquals(B, messages.find_definition( |
| 2095 'b.A.B', C, importer=self.Importer)) |
| 2096 self.assertEquals(C, messages.find_definition( |
| 2097 'b.A.B.C', C, importer=self.Importer)) |
| 2098 self.assertEquals(D, messages.find_definition( |
| 2099 'b.A.B.D', C, importer=self.Importer)) |
| 2100 |
| 2101 def testAbsoluteReference(self): |
| 2102 """Test finding absolute definition names.""" |
| 2103 # Define modules. |
| 2104 a = self.DefineModule('a') |
| 2105 b = self.DefineModule('a.a') |
| 2106 |
| 2107 # Define messages. |
| 2108 aA = self.DefineMessage('a', 'A') |
| 2109 aaA = self.DefineMessage('a.a', 'A') |
| 2110 |
| 2111 # Always find a.A. |
| 2112 self.assertEquals(aA, messages.find_definition('.a.A', None, |
| 2113 importer=self.Importer)) |
| 2114 self.assertEquals(aA, messages.find_definition('.a.A', a, |
| 2115 importer=self.Importer)) |
| 2116 self.assertEquals(aA, messages.find_definition('.a.A', aA, |
| 2117 importer=self.Importer)) |
| 2118 self.assertEquals(aA, messages.find_definition('.a.A', aaA, |
| 2119 importer=self.Importer)) |
| 2120 |
| 2121 def testFindEnum(self): |
| 2122 """Test that Enums are found.""" |
| 2123 class Color(messages.Enum): |
| 2124 pass |
| 2125 A = self.DefineMessage('a', 'A', {'Color': Color}) |
| 2126 |
| 2127 self.assertEquals( |
| 2128 Color, |
| 2129 messages.find_definition('Color', A, importer=self.Importer)) |
| 2130 |
| 2131 def testFalseScope(self): |
| 2132 """Test Message definitions nested in strange objects are hidden.""" |
| 2133 global X |
| 2134 |
| 2135 class X(object): |
| 2136 |
| 2137 class A(messages.Message): |
| 2138 pass |
| 2139 |
| 2140 self.assertRaises(TypeError, messages.find_definition, 'A', X) |
| 2141 self.assertRaises(messages.DefinitionNotFoundError, |
| 2142 messages.find_definition, |
| 2143 'X.A', sys.modules[__name__]) |
| 2144 |
| 2145 def testSearchAttributeFirst(self): |
| 2146 """Make sure not faked out by module, but continues searching.""" |
| 2147 A = self.DefineMessage('a', 'A') |
| 2148 module_A = self.DefineModule('a.A') |
| 2149 |
| 2150 self.assertEquals(A, messages.find_definition( |
| 2151 'a.A', None, importer=self.Importer)) |
| 2152 |
| 2153 |
| 2154 def main(): |
| 2155 unittest.main() |
| 2156 |
| 2157 |
| 2158 if __name__ == '__main__': |
| 2159 main() |
OLD | NEW |