Best JavaScript code snippet using playwright-internal
testpatch.py
Source:testpatch.py
...98 "patch not restored")99 def test_object_lookup_is_quite_lazy(self):100 global something101 original = something102 @patch('%s.something' % __name__, sentinel.Something2)103 def test():104 pass105 try:106 something = sentinel.replacement_value107 test()108 self.assertEqual(something, sentinel.replacement_value)109 finally:110 something = original111 def test_patch(self):112 @patch('%s.something' % __name__, sentinel.Something2)113 def test():114 self.assertEqual(PTModule.something, sentinel.Something2,115 "unpatched")116 test()117 self.assertEqual(PTModule.something, sentinel.Something,118 "patch not restored")119 @patch('%s.something' % __name__, sentinel.Something2)120 @patch('%s.something_else' % __name__, sentinel.SomethingElse)121 def test():122 self.assertEqual(PTModule.something, sentinel.Something2,123 "unpatched")124 self.assertEqual(PTModule.something_else, sentinel.SomethingElse,125 "unpatched")126 self.assertEqual(PTModule.something, sentinel.Something,127 "patch not restored")128 self.assertEqual(PTModule.something_else, sentinel.SomethingElse,129 "patch not restored")130 # Test the patching and restoring works a second time131 test()132 self.assertEqual(PTModule.something, sentinel.Something,133 "patch not restored")134 self.assertEqual(PTModule.something_else, sentinel.SomethingElse,135 "patch not restored")136 mock = Mock()137 mock.return_value = sentinel.Handle138 @patch('%s.open' % builtin_string, mock)139 def test():140 self.assertEqual(open('filename', 'r'), sentinel.Handle,141 "open not patched")142 test()143 test()144 self.assertNotEqual(open, mock, "patch not restored")145 def test_patch_class_attribute(self):146 @patch('%s.SomeClass.class_attribute' % __name__,147 sentinel.ClassAttribute)148 def test():149 self.assertEqual(PTModule.SomeClass.class_attribute,150 sentinel.ClassAttribute, "unpatched")151 test()152 self.assertIsNone(PTModule.SomeClass.class_attribute,153 "patch not restored")154 def test_patchobject_with_default_mock(self):155 class Test(object):156 something = sentinel.Original157 something2 = sentinel.Original2158 @patch.object(Test, 'something')159 def test(mock):160 self.assertEqual(mock, Test.something,161 "Mock not passed into test function")162 self.assertIsInstance(mock, MagicMock,163 "patch with two arguments did not create a mock")164 test()165 @patch.object(Test, 'something')166 @patch.object(Test, 'something2')167 def test(this1, this2, mock1, mock2):168 self.assertEqual(this1, sentinel.this1,169 "Patched function didn't receive initial argument")170 self.assertEqual(this2, sentinel.this2,171 "Patched function didn't receive second argument")172 self.assertEqual(mock1, Test.something2,173 "Mock not passed into test function")174 self.assertEqual(mock2, Test.something,175 "Second Mock not passed into test function")176 self.assertIsInstance(mock2, MagicMock,177 "patch with two arguments did not create a mock")178 self.assertIsInstance(mock2, MagicMock,179 "patch with two arguments did not create a mock")180 # A hack to test that new mocks are passed the second time181 self.assertNotEqual(outerMock1, mock1, "unexpected value for mock1")182 self.assertNotEqual(outerMock2, mock2, "unexpected value for mock1")183 return mock1, mock2184 outerMock1 = outerMock2 = None185 outerMock1, outerMock2 = test(sentinel.this1, sentinel.this2)186 # Test that executing a second time creates new mocks187 test(sentinel.this1, sentinel.this2)188 def test_patch_with_spec(self):189 @patch('%s.SomeClass' % __name__, spec=SomeClass)190 def test(MockSomeClass):191 self.assertEqual(SomeClass, MockSomeClass)192 self.assertTrue(is_instance(SomeClass.wibble, MagicMock))193 self.assertRaises(AttributeError, lambda: SomeClass.not_wibble)194 test()195 def test_patchobject_with_spec(self):196 @patch.object(SomeClass, 'class_attribute', spec=SomeClass)197 def test(MockAttribute):198 self.assertEqual(SomeClass.class_attribute, MockAttribute)199 self.assertTrue(is_instance(SomeClass.class_attribute.wibble,200 MagicMock))201 self.assertRaises(AttributeError,202 lambda: SomeClass.class_attribute.not_wibble)203 test()204 def test_patch_with_spec_as_list(self):205 @patch('%s.SomeClass' % __name__, spec=['wibble'])206 def test(MockSomeClass):207 self.assertEqual(SomeClass, MockSomeClass)208 self.assertTrue(is_instance(SomeClass.wibble, MagicMock))209 self.assertRaises(AttributeError, lambda: SomeClass.not_wibble)210 test()211 def test_patchobject_with_spec_as_list(self):212 @patch.object(SomeClass, 'class_attribute', spec=['wibble'])213 def test(MockAttribute):214 self.assertEqual(SomeClass.class_attribute, MockAttribute)215 self.assertTrue(is_instance(SomeClass.class_attribute.wibble,216 MagicMock))217 self.assertRaises(AttributeError,218 lambda: SomeClass.class_attribute.not_wibble)219 test()220 def test_nested_patch_with_spec_as_list(self):221 # regression test for nested decorators222 @patch('%s.open' % builtin_string)223 @patch('%s.SomeClass' % __name__, spec=['wibble'])224 def test(MockSomeClass, MockOpen):225 self.assertEqual(SomeClass, MockSomeClass)226 self.assertTrue(is_instance(SomeClass.wibble, MagicMock))227 self.assertRaises(AttributeError, lambda: SomeClass.not_wibble)228 test()229 def test_patch_with_spec_as_boolean(self):230 @patch('%s.SomeClass' % __name__, spec=True)231 def test(MockSomeClass):232 self.assertEqual(SomeClass, MockSomeClass)233 # Should not raise attribute error234 MockSomeClass.wibble235 self.assertRaises(AttributeError, lambda: MockSomeClass.not_wibble)236 test()237 def test_patch_object_with_spec_as_boolean(self):238 @patch.object(PTModule, 'SomeClass', spec=True)239 def test(MockSomeClass):240 self.assertEqual(SomeClass, MockSomeClass)241 # Should not raise attribute error242 MockSomeClass.wibble243 self.assertRaises(AttributeError, lambda: MockSomeClass.not_wibble)244 test()245 def test_patch_class_acts_with_spec_is_inherited(self):246 @patch('%s.SomeClass' % __name__, spec=True)247 def test(MockSomeClass):248 self.assertTrue(is_instance(MockSomeClass, MagicMock))249 instance = MockSomeClass()250 self.assertNotCallable(instance)251 # Should not raise attribute error252 instance.wibble253 self.assertRaises(AttributeError, lambda: instance.not_wibble)254 test()255 def test_patch_with_create_mocks_non_existent_attributes(self):256 @patch('%s.frooble' % builtin_string, sentinel.Frooble, create=True)257 def test():258 self.assertEqual(frooble, sentinel.Frooble)259 test()260 self.assertRaises(NameError, lambda: frooble)261 def test_patchobject_with_create_mocks_non_existent_attributes(self):262 @patch.object(SomeClass, 'frooble', sentinel.Frooble, create=True)263 def test():264 self.assertEqual(SomeClass.frooble, sentinel.Frooble)265 test()266 self.assertFalse(hasattr(SomeClass, 'frooble'))267 def test_patch_wont_create_by_default(self):268 try:269 @patch('%s.frooble' % builtin_string, sentinel.Frooble)270 def test():271 self.assertEqual(frooble, sentinel.Frooble)272 test()273 except AttributeError:274 pass275 else:276 self.fail('Patching non existent attributes should fail')277 self.assertRaises(NameError, lambda: frooble)278 def test_patchobject_wont_create_by_default(self):279 try:280 @patch.object(SomeClass, 'ord', sentinel.Frooble)281 def test():282 self.fail('Patching non existent attributes should fail')283 test()284 except AttributeError:285 pass286 else:287 self.fail('Patching non existent attributes should fail')288 self.assertFalse(hasattr(SomeClass, 'ord'))289 def test_patch_builtins_without_create(self):290 @patch(__name__+'.ord')291 def test_ord(mock_ord):292 mock_ord.return_value = 101293 return ord('c')294 @patch(__name__+'.open')295 def test_open(mock_open):296 m = mock_open.return_value297 m.read.return_value = 'abcd'298 fobj = open('doesnotexists.txt')299 data = fobj.read()300 fobj.close()301 return data302 self.assertEqual(test_ord(), 101)303 self.assertEqual(test_open(), 'abcd')304 def test_patch_with_static_methods(self):305 class Foo(object):306 @staticmethod307 def woot():308 return sentinel.Static309 @patch.object(Foo, 'woot', staticmethod(lambda: sentinel.Patched))310 def anonymous():311 self.assertEqual(Foo.woot(), sentinel.Patched)312 anonymous()313 self.assertEqual(Foo.woot(), sentinel.Static)314 def test_patch_local(self):315 foo = sentinel.Foo316 @patch.object(sentinel, 'Foo', 'Foo')317 def anonymous():318 self.assertEqual(sentinel.Foo, 'Foo')319 anonymous()320 self.assertEqual(sentinel.Foo, foo)321 def test_patch_slots(self):322 class Foo(object):323 __slots__ = ('Foo',)324 foo = Foo()325 foo.Foo = sentinel.Foo326 @patch.object(foo, 'Foo', 'Foo')327 def anonymous():328 self.assertEqual(foo.Foo, 'Foo')329 anonymous()330 self.assertEqual(foo.Foo, sentinel.Foo)331 def test_patchobject_class_decorator(self):332 class Something(object):333 attribute = sentinel.Original334 class Foo(object):335 def test_method(other_self):336 self.assertEqual(Something.attribute, sentinel.Patched,337 "unpatched")338 def not_test_method(other_self):339 self.assertEqual(Something.attribute, sentinel.Original,340 "non-test method patched")341 Foo = patch.object(Something, 'attribute', sentinel.Patched)(Foo)342 f = Foo()343 f.test_method()344 f.not_test_method()345 self.assertEqual(Something.attribute, sentinel.Original,346 "patch not restored")347 def test_patch_class_decorator(self):348 class Something(object):349 attribute = sentinel.Original350 class Foo(object):351 def test_method(other_self, mock_something):352 self.assertEqual(PTModule.something, mock_something,353 "unpatched")354 def not_test_method(other_self):355 self.assertEqual(PTModule.something, sentinel.Something,356 "non-test method patched")357 Foo = patch('%s.something' % __name__)(Foo)358 f = Foo()359 f.test_method()360 f.not_test_method()361 self.assertEqual(Something.attribute, sentinel.Original,362 "patch not restored")363 self.assertEqual(PTModule.something, sentinel.Something,364 "patch not restored")365 def test_patchobject_twice(self):366 class Something(object):367 attribute = sentinel.Original368 next_attribute = sentinel.Original2369 @patch.object(Something, 'attribute', sentinel.Patched)370 @patch.object(Something, 'attribute', sentinel.Patched)371 def test():372 self.assertEqual(Something.attribute, sentinel.Patched, "unpatched")373 test()374 self.assertEqual(Something.attribute, sentinel.Original,375 "patch not restored")376 def test_patch_dict(self):377 foo = {'initial': object(), 'other': 'something'}378 original = foo.copy()379 @patch.dict(foo)380 def test():381 foo['a'] = 3382 del foo['initial']383 foo['other'] = 'something else'384 test()385 self.assertEqual(foo, original)386 @patch.dict(foo, {'a': 'b'})387 def test():388 self.assertEqual(len(foo), 3)389 self.assertEqual(foo['a'], 'b')390 test()391 self.assertEqual(foo, original)392 @patch.dict(foo, [('a', 'b')])393 def test():394 self.assertEqual(len(foo), 3)395 self.assertEqual(foo['a'], 'b')396 test()397 self.assertEqual(foo, original)398 def test_patch_dict_with_container_object(self):399 foo = Container()400 foo['initial'] = object()401 foo['other'] = 'something'402 original = foo.values.copy()403 @patch.dict(foo)404 def test():405 foo['a'] = 3406 del foo['initial']407 foo['other'] = 'something else'408 test()409 self.assertEqual(foo.values, original)410 @patch.dict(foo, {'a': 'b'})411 def test():412 self.assertEqual(len(foo.values), 3)413 self.assertEqual(foo['a'], 'b')414 test()415 self.assertEqual(foo.values, original)416 def test_patch_dict_with_clear(self):417 foo = {'initial': object(), 'other': 'something'}418 original = foo.copy()419 @patch.dict(foo, clear=True)420 def test():421 self.assertEqual(foo, {})422 foo['a'] = 3423 foo['other'] = 'something else'424 test()425 self.assertEqual(foo, original)426 @patch.dict(foo, {'a': 'b'}, clear=True)427 def test():428 self.assertEqual(foo, {'a': 'b'})429 test()430 self.assertEqual(foo, original)431 @patch.dict(foo, [('a', 'b')], clear=True)432 def test():433 self.assertEqual(foo, {'a': 'b'})434 test()435 self.assertEqual(foo, original)436 def test_patch_dict_with_container_object_and_clear(self):437 foo = Container()438 foo['initial'] = object()439 foo['other'] = 'something'440 original = foo.values.copy()441 @patch.dict(foo, clear=True)442 def test():443 self.assertEqual(foo.values, {})444 foo['a'] = 3445 foo['other'] = 'something else'446 test()447 self.assertEqual(foo.values, original)448 @patch.dict(foo, {'a': 'b'}, clear=True)449 def test():450 self.assertEqual(foo.values, {'a': 'b'})451 test()452 self.assertEqual(foo.values, original)453 def test_name_preserved(self):454 foo = {}455 @patch('%s.SomeClass' % __name__, object())456 @patch('%s.SomeClass' % __name__, object(), autospec=True)457 @patch.object(SomeClass, object())458 @patch.dict(foo)459 def some_name():460 pass461 self.assertEqual(some_name.__name__, 'some_name')462 def test_patch_with_exception(self):463 foo = {}464 @patch.dict(foo, {'a': 'b'})465 def test():466 raise NameError('Konrad')467 try:468 test()469 except NameError:470 pass471 else:472 self.fail('NameError not raised by test')473 self.assertEqual(foo, {})474 def test_patch_dict_with_string(self):475 @patch.dict('os.environ', {'konrad_delong': 'some value'})476 def test():477 self.assertIn('konrad_delong', os.environ)478 test()479 def test_patch_descriptor(self):480 # would be some effort to fix this - we could special case the481 # builtin descriptors: classmethod, property, staticmethod482 return483 class Nothing(object):484 foo = None485 class Something(object):486 foo = {}487 @patch.object(Nothing, 'foo', 2)488 @classmethod489 def klass(cls):490 self.assertIs(cls, Something)491 @patch.object(Nothing, 'foo', 2)492 @staticmethod493 def static(arg):494 return arg495 @patch.dict(foo)496 @classmethod497 def klass_dict(cls):498 self.assertIs(cls, Something)499 @patch.dict(foo)500 @staticmethod501 def static_dict(arg):502 return arg503 # these will raise exceptions if patching descriptors is broken504 self.assertEqual(Something.static('f00'), 'f00')505 Something.klass()506 self.assertEqual(Something.static_dict('f00'), 'f00')507 Something.klass_dict()508 something = Something()509 self.assertEqual(something.static('f00'), 'f00')510 something.klass()511 self.assertEqual(something.static_dict('f00'), 'f00')512 something.klass_dict()513 def test_patch_spec_set(self):514 @patch('%s.SomeClass' % __name__, spec=SomeClass, spec_set=True)515 def test(MockClass):516 MockClass.z = 'foo'517 self.assertRaises(AttributeError, test)518 @patch.object(support, 'SomeClass', spec=SomeClass, spec_set=True)519 def test(MockClass):520 MockClass.z = 'foo'521 self.assertRaises(AttributeError, test)522 @patch('%s.SomeClass' % __name__, spec_set=True)523 def test(MockClass):524 MockClass.z = 'foo'525 self.assertRaises(AttributeError, test)526 @patch.object(support, 'SomeClass', spec_set=True)527 def test(MockClass):528 MockClass.z = 'foo'529 self.assertRaises(AttributeError, test)530 def test_spec_set_inherit(self):531 @patch('%s.SomeClass' % __name__, spec_set=True)532 def test(MockClass):533 instance = MockClass()534 instance.z = 'foo'535 self.assertRaises(AttributeError, test)536 def test_patch_start_stop(self):537 original = something538 patcher = patch('%s.something' % __name__)539 self.assertIs(something, original)540 mock = patcher.start()541 try:542 self.assertIsNot(mock, original)543 self.assertIs(something, mock)544 finally:545 patcher.stop()546 self.assertIs(something, original)547 def test_stop_without_start(self):548 patcher = patch(foo_name, 'bar', 3)549 # calling stop without start used to produce a very obscure error550 self.assertRaises(RuntimeError, patcher.stop)551 def test_patchobject_start_stop(self):552 original = something553 patcher = patch.object(PTModule, 'something', 'foo')554 self.assertIs(something, original)555 replaced = patcher.start()556 try:557 self.assertEqual(replaced, 'foo')558 self.assertIs(something, replaced)559 finally:560 patcher.stop()561 self.assertIs(something, original)562 def test_patch_dict_start_stop(self):563 d = {'foo': 'bar'}564 original = d.copy()565 patcher = patch.dict(d, [('spam', 'eggs')], clear=True)566 self.assertEqual(d, original)567 patcher.start()568 try:569 self.assertEqual(d, {'spam': 'eggs'})570 finally:571 patcher.stop()572 self.assertEqual(d, original)573 def test_patch_dict_class_decorator(self):574 this = self575 d = {'spam': 'eggs'}576 original = d.copy()577 class Test(object):578 def test_first(self):579 this.assertEqual(d, {'foo': 'bar'})580 def test_second(self):581 this.assertEqual(d, {'foo': 'bar'})582 Test = patch.dict(d, {'foo': 'bar'}, clear=True)(Test)583 self.assertEqual(d, original)584 test = Test()585 test.test_first()586 self.assertEqual(d, original)587 test.test_second()588 self.assertEqual(d, original)589 test = Test()590 test.test_first()591 self.assertEqual(d, original)592 test.test_second()593 self.assertEqual(d, original)594 def test_get_only_proxy(self):595 class Something(object):596 foo = 'foo'597 class SomethingElse:598 foo = 'foo'599 for thing in Something, SomethingElse, Something(), SomethingElse:600 proxy = _get_proxy(thing)601 @patch.object(proxy, 'foo', 'bar')602 def test():603 self.assertEqual(proxy.foo, 'bar')604 test()605 self.assertEqual(proxy.foo, 'foo')606 self.assertEqual(thing.foo, 'foo')607 self.assertNotIn('foo', proxy.__dict__)608 def test_get_set_delete_proxy(self):609 class Something(object):610 foo = 'foo'611 class SomethingElse:612 foo = 'foo'613 for thing in Something, SomethingElse, Something(), SomethingElse:614 proxy = _get_proxy(Something, get_only=False)615 @patch.object(proxy, 'foo', 'bar')616 def test():617 self.assertEqual(proxy.foo, 'bar')618 test()619 self.assertEqual(proxy.foo, 'foo')620 self.assertEqual(thing.foo, 'foo')621 self.assertNotIn('foo', proxy.__dict__)622 def test_patch_keyword_args(self):623 kwargs = {'side_effect': KeyError, 'foo.bar.return_value': 33,624 'foo': MagicMock()}625 patcher = patch(foo_name, **kwargs)626 mock = patcher.start()627 patcher.stop()628 self.assertRaises(KeyError, mock)629 self.assertEqual(mock.foo.bar(), 33)630 self.assertIsInstance(mock.foo, MagicMock)631 def test_patch_object_keyword_args(self):632 kwargs = {'side_effect': KeyError, 'foo.bar.return_value': 33,633 'foo': MagicMock()}634 patcher = patch.object(Foo, 'f', **kwargs)635 mock = patcher.start()636 patcher.stop()637 self.assertRaises(KeyError, mock)638 self.assertEqual(mock.foo.bar(), 33)639 self.assertIsInstance(mock.foo, MagicMock)640 def test_patch_dict_keyword_args(self):641 original = {'foo': 'bar'}642 copy = original.copy()643 patcher = patch.dict(original, foo=3, bar=4, baz=5)644 patcher.start()645 try:646 self.assertEqual(original, dict(foo=3, bar=4, baz=5))647 finally:648 patcher.stop()649 self.assertEqual(original, copy)650 def test_autospec(self):651 class Boo(object):652 def __init__(self, a):653 pass654 def f(self, a):655 pass656 def g(self):657 pass658 foo = 'bar'659 class Bar(object):660 def a(self):661 pass662 def _test(mock):663 mock(1)664 mock.assert_called_with(1)665 self.assertRaises(TypeError, mock)666 def _test2(mock):667 mock.f(1)668 mock.f.assert_called_with(1)669 self.assertRaises(TypeError, mock.f)670 mock.g()671 mock.g.assert_called_with()672 self.assertRaises(TypeError, mock.g, 1)673 self.assertRaises(AttributeError, getattr, mock, 'h')674 mock.foo.lower()675 mock.foo.lower.assert_called_with()676 self.assertRaises(AttributeError, getattr, mock.foo, 'bar')677 mock.Bar()678 mock.Bar.assert_called_with()679 mock.Bar.a()680 mock.Bar.a.assert_called_with()681 self.assertRaises(TypeError, mock.Bar.a, 1)682 mock.Bar().a()683 mock.Bar().a.assert_called_with()684 self.assertRaises(TypeError, mock.Bar().a, 1)685 self.assertRaises(AttributeError, getattr, mock.Bar, 'b')686 self.assertRaises(AttributeError, getattr, mock.Bar(), 'b')687 def function(mock):688 _test(mock)689 _test2(mock)690 _test2(mock(1))691 self.assertIs(mock, Foo)692 return mock693 test = patch(foo_name, autospec=True)(function)694 mock = test()695 self.assertIsNot(Foo, mock)696 # test patching a second time works697 test()698 module = sys.modules[__name__]699 test = patch.object(module, 'Foo', autospec=True)(function)700 mock = test()701 self.assertIsNot(Foo, mock)702 # test patching a second time works703 test()704 def test_autospec_function(self):705 @patch('%s.function' % __name__, autospec=True)706 def test(mock):707 function(1)708 function.assert_called_with(1)709 function(2, 3)710 function.assert_called_with(2, 3)711 self.assertRaises(TypeError, function)712 self.assertRaises(AttributeError, getattr, function, 'foo')713 test()714 def test_autospec_keywords(self):715 @patch('%s.function' % __name__, autospec=True,716 return_value=3)717 def test(mock_function):718 #self.assertEqual(function.abc, 'foo')719 return function(1, 2)720 result = test()721 self.assertEqual(result, 3)722 def test_autospec_with_new(self):723 patcher = patch('%s.function' % __name__, new=3, autospec=True)724 self.assertRaises(TypeError, patcher.start)725 module = sys.modules[__name__]726 patcher = patch.object(module, 'function', new=3, autospec=True)727 self.assertRaises(TypeError, patcher.start)728 def test_autospec_with_object(self):729 class Bar(Foo):730 extra = []731 patcher = patch(foo_name, autospec=Bar)732 mock = patcher.start()733 try:734 self.assertIsInstance(mock, Bar)735 self.assertIsInstance(mock.extra, list)736 finally:737 patcher.stop()738 def test_autospec_inherits(self):739 FooClass = Foo740 patcher = patch(foo_name, autospec=True)741 mock = patcher.start()742 try:743 self.assertIsInstance(mock, FooClass)744 self.assertIsInstance(mock(3), FooClass)745 finally:746 patcher.stop()747 def test_autospec_name(self):748 patcher = patch(foo_name, autospec=True)749 mock = patcher.start()750 try:751 self.assertIn(" name='Foo'", repr(mock))752 self.assertIn(" name='Foo.f'", repr(mock.f))753 self.assertIn(" name='Foo()'", repr(mock(None)))754 self.assertIn(" name='Foo().f'", repr(mock(None).f))755 finally:756 patcher.stop()757 def test_tracebacks(self):758 @patch.object(Foo, 'f', object())759 def test():760 raise AssertionError761 try:762 test()763 except:764 err = sys.exc_info()765 result = unittest.TextTestResult(None, None, 0)766 traceback = result._exc_info_to_string(err, self)767 self.assertIn('raise AssertionError', traceback)768 def test_new_callable_patch(self):769 patcher = patch(foo_name, new_callable=NonCallableMagicMock)770 m1 = patcher.start()771 patcher.stop()772 m2 = patcher.start()773 patcher.stop()774 self.assertIsNot(m1, m2)775 for mock in m1, m2:776 self.assertNotCallable(m1)777 def test_new_callable_patch_object(self):778 patcher = patch.object(Foo, 'f', new_callable=NonCallableMagicMock)779 m1 = patcher.start()780 patcher.stop()781 m2 = patcher.start()782 patcher.stop()783 self.assertIsNot(m1, m2)784 for mock in m1, m2:785 self.assertNotCallable(m1)786 def test_new_callable_keyword_arguments(self):787 class Bar(object):788 kwargs = None789 def __init__(self, **kwargs):790 Bar.kwargs = kwargs791 patcher = patch(foo_name, new_callable=Bar, arg1=1, arg2=2)792 m = patcher.start()793 try:794 self.assertIs(type(m), Bar)795 self.assertEqual(Bar.kwargs, dict(arg1=1, arg2=2))796 finally:797 patcher.stop()798 def test_new_callable_spec(self):799 class Bar(object):800 kwargs = None801 def __init__(self, **kwargs):802 Bar.kwargs = kwargs803 patcher = patch(foo_name, new_callable=Bar, spec=Bar)804 patcher.start()805 try:806 self.assertEqual(Bar.kwargs, dict(spec=Bar))807 finally:808 patcher.stop()809 patcher = patch(foo_name, new_callable=Bar, spec_set=Bar)810 patcher.start()811 try:812 self.assertEqual(Bar.kwargs, dict(spec_set=Bar))813 finally:814 patcher.stop()815 def test_new_callable_create(self):816 non_existent_attr = '%s.weeeee' % foo_name817 p = patch(non_existent_attr, new_callable=NonCallableMock)818 self.assertRaises(AttributeError, p.start)819 p = patch(non_existent_attr, new_callable=NonCallableMock,820 create=True)821 m = p.start()822 try:823 self.assertNotCallable(m, magic=False)824 finally:825 p.stop()826 def test_new_callable_incompatible_with_new(self):827 self.assertRaises(828 ValueError, patch, foo_name, new=object(), new_callable=MagicMock829 )830 self.assertRaises(831 ValueError, patch.object, Foo, 'f', new=object(),832 new_callable=MagicMock833 )834 def test_new_callable_incompatible_with_autospec(self):835 self.assertRaises(836 ValueError, patch, foo_name, new_callable=MagicMock,837 autospec=True838 )839 self.assertRaises(840 ValueError, patch.object, Foo, 'f', new_callable=MagicMock,841 autospec=True842 )843 def test_new_callable_inherit_for_mocks(self):844 class MockSub(Mock):845 pass846 MockClasses = (847 NonCallableMock, NonCallableMagicMock, MagicMock, Mock, MockSub848 )849 for Klass in MockClasses:850 for arg in 'spec', 'spec_set':851 kwargs = {arg: True}852 p = patch(foo_name, new_callable=Klass, **kwargs)853 m = p.start()854 try:855 instance = m.return_value856 self.assertRaises(AttributeError, getattr, instance, 'x')857 finally:858 p.stop()859 def test_new_callable_inherit_non_mock(self):860 class NotAMock(object):861 def __init__(self, spec):862 self.spec = spec863 p = patch(foo_name, new_callable=NotAMock, spec=True)864 m = p.start()865 try:866 self.assertTrue(is_instance(m, NotAMock))867 self.assertRaises(AttributeError, getattr, m, 'return_value')868 finally:869 p.stop()870 self.assertEqual(m.spec, Foo)871 def test_new_callable_class_decorating(self):872 test = self873 original = Foo874 class SomeTest(object):875 def _test(self, mock_foo):876 test.assertIsNot(Foo, original)877 test.assertIs(Foo, mock_foo)878 test.assertIsInstance(Foo, SomeClass)879 def test_two(self, mock_foo):880 self._test(mock_foo)881 def test_one(self, mock_foo):882 self._test(mock_foo)883 SomeTest = patch(foo_name, new_callable=SomeClass)(SomeTest)884 SomeTest().test_one()885 SomeTest().test_two()886 self.assertIs(Foo, original)887 def test_patch_multiple(self):888 original_foo = Foo889 original_f = Foo.f890 original_g = Foo.g891 patcher1 = patch.multiple(foo_name, f=1, g=2)892 patcher2 = patch.multiple(Foo, f=1, g=2)893 for patcher in patcher1, patcher2:894 patcher.start()895 try:896 self.assertIs(Foo, original_foo)897 self.assertEqual(Foo.f, 1)898 self.assertEqual(Foo.g, 2)899 finally:900 patcher.stop()901 self.assertIs(Foo, original_foo)902 self.assertEqual(Foo.f, original_f)903 self.assertEqual(Foo.g, original_g)904 @patch.multiple(foo_name, f=3, g=4)905 def test():906 self.assertIs(Foo, original_foo)907 self.assertEqual(Foo.f, 3)908 self.assertEqual(Foo.g, 4)909 test()910 def test_patch_multiple_no_kwargs(self):911 self.assertRaises(ValueError, patch.multiple, foo_name)912 self.assertRaises(ValueError, patch.multiple, Foo)913 def test_patch_multiple_create_mocks(self):914 original_foo = Foo915 original_f = Foo.f916 original_g = Foo.g917 @patch.multiple(foo_name, f=DEFAULT, g=3, foo=DEFAULT)918 def test(f, foo):919 self.assertIs(Foo, original_foo)920 self.assertIs(Foo.f, f)921 self.assertEqual(Foo.g, 3)922 self.assertIs(Foo.foo, foo)923 self.assertTrue(is_instance(f, MagicMock))924 self.assertTrue(is_instance(foo, MagicMock))925 test()926 self.assertEqual(Foo.f, original_f)927 self.assertEqual(Foo.g, original_g)928 def test_patch_multiple_create_mocks_different_order(self):929 # bug revealed by Jython!930 original_f = Foo.f931 original_g = Foo.g932 patcher = patch.object(Foo, 'f', 3)933 patcher.attribute_name = 'f'934 other = patch.object(Foo, 'g', DEFAULT)935 other.attribute_name = 'g'936 patcher.additional_patchers = [other]937 @patcher938 def test(g):939 self.assertIs(Foo.g, g)940 self.assertEqual(Foo.f, 3)941 test()942 self.assertEqual(Foo.f, original_f)943 self.assertEqual(Foo.g, original_g)944 def test_patch_multiple_stacked_decorators(self):945 original_foo = Foo946 original_f = Foo.f947 original_g = Foo.g948 @patch.multiple(foo_name, f=DEFAULT)949 @patch.multiple(foo_name, foo=DEFAULT)950 @patch(foo_name + '.g')951 def test1(g, **kwargs):952 _test(g, **kwargs)953 @patch.multiple(foo_name, f=DEFAULT)954 @patch(foo_name + '.g')955 @patch.multiple(foo_name, foo=DEFAULT)956 def test2(g, **kwargs):957 _test(g, **kwargs)958 @patch(foo_name + '.g')959 @patch.multiple(foo_name, f=DEFAULT)960 @patch.multiple(foo_name, foo=DEFAULT)961 def test3(g, **kwargs):962 _test(g, **kwargs)963 def _test(g, **kwargs):964 f = kwargs.pop('f')965 foo = kwargs.pop('foo')966 self.assertFalse(kwargs)967 self.assertIs(Foo, original_foo)968 self.assertIs(Foo.f, f)969 self.assertIs(Foo.g, g)970 self.assertIs(Foo.foo, foo)971 self.assertTrue(is_instance(f, MagicMock))972 self.assertTrue(is_instance(g, MagicMock))973 self.assertTrue(is_instance(foo, MagicMock))974 test1()975 test2()976 test3()977 self.assertEqual(Foo.f, original_f)978 self.assertEqual(Foo.g, original_g)979 def test_patch_multiple_create_mocks_patcher(self):980 original_foo = Foo981 original_f = Foo.f982 original_g = Foo.g983 patcher = patch.multiple(foo_name, f=DEFAULT, g=3, foo=DEFAULT)984 result = patcher.start()985 try:986 f = result['f']987 foo = result['foo']988 self.assertEqual(set(result), set(['f', 'foo']))989 self.assertIs(Foo, original_foo)990 self.assertIs(Foo.f, f)991 self.assertIs(Foo.foo, foo)992 self.assertTrue(is_instance(f, MagicMock))993 self.assertTrue(is_instance(foo, MagicMock))994 finally:995 patcher.stop()996 self.assertEqual(Foo.f, original_f)997 self.assertEqual(Foo.g, original_g)998 def test_patch_multiple_decorating_class(self):999 test = self1000 original_foo = Foo1001 original_f = Foo.f1002 original_g = Foo.g1003 class SomeTest(object):1004 def _test(self, f, foo):1005 test.assertIs(Foo, original_foo)1006 test.assertIs(Foo.f, f)1007 test.assertEqual(Foo.g, 3)1008 test.assertIs(Foo.foo, foo)1009 test.assertTrue(is_instance(f, MagicMock))1010 test.assertTrue(is_instance(foo, MagicMock))1011 def test_two(self, f, foo):1012 self._test(f, foo)1013 def test_one(self, f, foo):1014 self._test(f, foo)1015 SomeTest = patch.multiple(1016 foo_name, f=DEFAULT, g=3, foo=DEFAULT1017 )(SomeTest)1018 thing = SomeTest()1019 thing.test_one()1020 thing.test_two()1021 self.assertEqual(Foo.f, original_f)1022 self.assertEqual(Foo.g, original_g)1023 def test_patch_multiple_create(self):1024 patcher = patch.multiple(Foo, blam='blam')1025 self.assertRaises(AttributeError, patcher.start)1026 patcher = patch.multiple(Foo, blam='blam', create=True)1027 patcher.start()1028 try:1029 self.assertEqual(Foo.blam, 'blam')1030 finally:1031 patcher.stop()1032 self.assertFalse(hasattr(Foo, 'blam'))1033 def test_patch_multiple_spec_set(self):1034 # if spec_set works then we can assume that spec and autospec also1035 # work as the underlying machinery is the same1036 patcher = patch.multiple(Foo, foo=DEFAULT, spec_set=['a', 'b'])1037 result = patcher.start()1038 try:1039 self.assertEqual(Foo.foo, result['foo'])1040 Foo.foo.a(1)1041 Foo.foo.b(2)1042 Foo.foo.a.assert_called_with(1)1043 Foo.foo.b.assert_called_with(2)1044 self.assertRaises(AttributeError, setattr, Foo.foo, 'c', None)1045 finally:1046 patcher.stop()1047 def test_patch_multiple_new_callable(self):1048 class Thing(object):1049 pass1050 patcher = patch.multiple(1051 Foo, f=DEFAULT, g=DEFAULT, new_callable=Thing1052 )1053 result = patcher.start()1054 try:1055 self.assertIs(Foo.f, result['f'])1056 self.assertIs(Foo.g, result['g'])1057 self.assertIsInstance(Foo.f, Thing)1058 self.assertIsInstance(Foo.g, Thing)1059 self.assertIsNot(Foo.f, Foo.g)1060 finally:1061 patcher.stop()1062 def test_nested_patch_failure(self):1063 original_f = Foo.f1064 original_g = Foo.g1065 @patch.object(Foo, 'g', 1)1066 @patch.object(Foo, 'missing', 1)1067 @patch.object(Foo, 'f', 1)1068 def thing1():1069 pass1070 @patch.object(Foo, 'missing', 1)1071 @patch.object(Foo, 'g', 1)1072 @patch.object(Foo, 'f', 1)1073 def thing2():1074 pass1075 @patch.object(Foo, 'g', 1)1076 @patch.object(Foo, 'f', 1)1077 @patch.object(Foo, 'missing', 1)1078 def thing3():1079 pass1080 for func in thing1, thing2, thing3:1081 self.assertRaises(AttributeError, func)1082 self.assertEqual(Foo.f, original_f)1083 self.assertEqual(Foo.g, original_g)1084 def test_new_callable_failure(self):1085 original_f = Foo.f1086 original_g = Foo.g1087 original_foo = Foo.foo1088 def crasher():1089 raise NameError('crasher')1090 @patch.object(Foo, 'g', 1)1091 @patch.object(Foo, 'foo', new_callable=crasher)1092 @patch.object(Foo, 'f', 1)1093 def thing1():1094 pass1095 @patch.object(Foo, 'foo', new_callable=crasher)1096 @patch.object(Foo, 'g', 1)1097 @patch.object(Foo, 'f', 1)1098 def thing2():1099 pass1100 @patch.object(Foo, 'g', 1)1101 @patch.object(Foo, 'f', 1)1102 @patch.object(Foo, 'foo', new_callable=crasher)1103 def thing3():1104 pass1105 for func in thing1, thing2, thing3:1106 self.assertRaises(NameError, func)1107 self.assertEqual(Foo.f, original_f)1108 self.assertEqual(Foo.g, original_g)1109 self.assertEqual(Foo.foo, original_foo)1110 def test_patch_multiple_failure(self):1111 original_f = Foo.f1112 original_g = Foo.g1113 patcher = patch.object(Foo, 'f', 1)1114 patcher.attribute_name = 'f'1115 good = patch.object(Foo, 'g', 1)1116 good.attribute_name = 'g'1117 bad = patch.object(Foo, 'missing', 1)1118 bad.attribute_name = 'missing'1119 for additionals in [good, bad], [bad, good]:1120 patcher.additional_patchers = additionals1121 @patcher1122 def func():1123 pass1124 self.assertRaises(AttributeError, func)1125 self.assertEqual(Foo.f, original_f)1126 self.assertEqual(Foo.g, original_g)1127 def test_patch_multiple_new_callable_failure(self):1128 original_f = Foo.f1129 original_g = Foo.g1130 original_foo = Foo.foo1131 def crasher():1132 raise NameError('crasher')1133 patcher = patch.object(Foo, 'f', 1)1134 patcher.attribute_name = 'f'1135 good = patch.object(Foo, 'g', 1)1136 good.attribute_name = 'g'1137 bad = patch.object(Foo, 'foo', new_callable=crasher)1138 bad.attribute_name = 'foo'1139 for additionals in [good, bad], [bad, good]:1140 patcher.additional_patchers = additionals1141 @patcher1142 def func():1143 pass1144 self.assertRaises(NameError, func)1145 self.assertEqual(Foo.f, original_f)1146 self.assertEqual(Foo.g, original_g)1147 self.assertEqual(Foo.foo, original_foo)1148 def test_patch_multiple_string_subclasses(self):1149 Foo = type('Foo', (str,), {'fish': 'tasty'})1150 foo = Foo()1151 @patch.multiple(foo, fish='nearly gone')1152 def test():1153 self.assertEqual(foo.fish, 'nearly gone')1154 test()1155 self.assertEqual(foo.fish, 'tasty')1156 @patch('unittest.mock.patch.TEST_PREFIX', 'foo')1157 def test_patch_test_prefix(self):1158 class Foo(object):1159 thing = 'original'1160 def foo_one(self):1161 return self.thing1162 def foo_two(self):1163 return self.thing1164 def test_one(self):1165 return self.thing1166 def test_two(self):1167 return self.thing1168 Foo = patch.object(Foo, 'thing', 'changed')(Foo)1169 foo = Foo()1170 self.assertEqual(foo.foo_one(), 'changed')1171 self.assertEqual(foo.foo_two(), 'changed')1172 self.assertEqual(foo.test_one(), 'original')1173 self.assertEqual(foo.test_two(), 'original')1174 @patch('unittest.mock.patch.TEST_PREFIX', 'bar')1175 def test_patch_dict_test_prefix(self):1176 class Foo(object):1177 def bar_one(self):1178 return dict(the_dict)1179 def bar_two(self):1180 return dict(the_dict)1181 def test_one(self):1182 return dict(the_dict)1183 def test_two(self):1184 return dict(the_dict)1185 the_dict = {'key': 'original'}1186 Foo = patch.dict(the_dict, key='changed')(Foo)1187 foo =Foo()1188 self.assertEqual(foo.bar_one(), {'key': 'changed'})1189 self.assertEqual(foo.bar_two(), {'key': 'changed'})1190 self.assertEqual(foo.test_one(), {'key': 'original'})1191 self.assertEqual(foo.test_two(), {'key': 'original'})1192 def test_patch_with_spec_mock_repr(self):1193 for arg in ('spec', 'autospec', 'spec_set'):1194 p = patch('%s.SomeClass' % __name__, **{arg: True})1195 m = p.start()1196 try:1197 self.assertIn(" name='SomeClass'", repr(m))1198 self.assertIn(" name='SomeClass.class_attribute'",1199 repr(m.class_attribute))1200 self.assertIn(" name='SomeClass()'", repr(m()))1201 self.assertIn(" name='SomeClass().class_attribute'",1202 repr(m().class_attribute))1203 finally:1204 p.stop()1205 def test_patch_nested_autospec_repr(self):1206 with patch('unittest.test.testmock.support', autospec=True) as m:1207 self.assertIn(" name='support.SomeClass.wibble()'",1208 repr(m.SomeClass.wibble()))1209 self.assertIn(" name='support.SomeClass().wibble()'",1210 repr(m.SomeClass().wibble()))1211 def test_mock_calls_with_patch(self):1212 for arg in ('spec', 'autospec', 'spec_set'):1213 p = patch('%s.SomeClass' % __name__, **{arg: True})1214 m = p.start()1215 try:1216 m.wibble()1217 kalls = [call.wibble()]1218 self.assertEqual(m.mock_calls, kalls)1219 self.assertEqual(m.method_calls, kalls)1220 self.assertEqual(m.wibble.mock_calls, [call()])1221 result = m()1222 kalls.append(call())1223 self.assertEqual(m.mock_calls, kalls)1224 result.wibble()1225 kalls.append(call().wibble())1226 self.assertEqual(m.mock_calls, kalls)1227 self.assertEqual(result.mock_calls, [call.wibble()])1228 self.assertEqual(result.wibble.mock_calls, [call()])1229 self.assertEqual(result.method_calls, [call.wibble()])1230 finally:1231 p.stop()1232 def test_patch_imports_lazily(self):1233 sys.modules.pop('squizz', None)1234 p1 = patch('squizz.squozz')1235 self.assertRaises(ImportError, p1.start)1236 squizz = Mock()1237 squizz.squozz = 61238 sys.modules['squizz'] = squizz1239 p1 = patch('squizz.squozz')1240 squizz.squozz = 31241 p1.start()1242 p1.stop()1243 self.assertEqual(squizz.squozz, 3)1244 def test_patch_propogrates_exc_on_exit(self):1245 class holder:1246 exc_info = None, None, None1247 class custom_patch(_patch):1248 def __exit__(self, etype=None, val=None, tb=None):1249 _patch.__exit__(self, etype, val, tb)1250 holder.exc_info = etype, val, tb1251 stop = __exit__1252 def with_custom_patch(target):1253 getter, attribute = _get_target(target)1254 return custom_patch(1255 getter, attribute, DEFAULT, None, False, None,1256 None, None, {}1257 )1258 @with_custom_patch('squizz.squozz')1259 def test(mock):1260 raise RuntimeError1261 self.assertRaises(RuntimeError, test)1262 self.assertIs(holder.exc_info[0], RuntimeError)1263 self.assertIsNotNone(holder.exc_info[1],1264 'exception value not propgated')1265 self.assertIsNotNone(holder.exc_info[2],1266 'exception traceback not propgated')1267 def test_create_and_specs(self):1268 for kwarg in ('spec', 'spec_set', 'autospec'):1269 p = patch('%s.doesnotexist' % __name__, create=True,1270 **{kwarg: True})1271 self.assertRaises(TypeError, p.start)1272 self.assertRaises(NameError, lambda: doesnotexist)1273 # check that spec with create is innocuous if the original exists1274 p = patch(MODNAME, create=True, **{kwarg: True})1275 p.start()1276 p.stop()1277 def test_multiple_specs(self):1278 original = PTModule1279 for kwarg in ('spec', 'spec_set'):1280 p = patch(MODNAME, autospec=0, **{kwarg: 0})1281 self.assertRaises(TypeError, p.start)1282 self.assertIs(PTModule, original)1283 for kwarg in ('spec', 'autospec'):1284 p = patch(MODNAME, spec_set=0, **{kwarg: 0})1285 self.assertRaises(TypeError, p.start)1286 self.assertIs(PTModule, original)1287 for kwarg in ('spec_set', 'autospec'):1288 p = patch(MODNAME, spec=0, **{kwarg: 0})1289 self.assertRaises(TypeError, p.start)1290 self.assertIs(PTModule, original)1291 def test_specs_false_instead_of_none(self):1292 p = patch(MODNAME, spec=False, spec_set=False, autospec=False)1293 mock = p.start()1294 try:1295 # no spec should have been set, so attribute access should not fail1296 mock.does_not_exist1297 mock.does_not_exist = 31298 finally:1299 p.stop()1300 def test_falsey_spec(self):1301 for kwarg in ('spec', 'autospec', 'spec_set'):1302 p = patch(MODNAME, **{kwarg: 0})1303 m = p.start()1304 try:1305 self.assertRaises(AttributeError, getattr, m, 'doesnotexit')1306 finally:1307 p.stop()1308 def test_spec_set_true(self):1309 for kwarg in ('spec', 'autospec'):1310 p = patch(MODNAME, spec_set=True, **{kwarg: True})1311 m = p.start()1312 try:1313 self.assertRaises(AttributeError, setattr, m,1314 'doesnotexist', 'something')1315 self.assertRaises(AttributeError, getattr, m, 'doesnotexist')1316 finally:1317 p.stop()1318 def test_callable_spec_as_list(self):1319 spec = ('__call__',)1320 p = patch(MODNAME, spec=spec)1321 m = p.start()1322 try:1323 self.assertTrue(callable(m))1324 finally:1325 p.stop()1326 def test_not_callable_spec_as_list(self):1327 spec = ('foo', 'bar')1328 p = patch(MODNAME, spec=spec)1329 m = p.start()1330 try:1331 self.assertFalse(callable(m))1332 finally:1333 p.stop()1334 def test_patch_stopall(self):1335 unlink = os.unlink1336 chdir = os.chdir1337 path = os.path1338 patch('os.unlink', something).start()1339 patch('os.chdir', something_else).start()1340 @patch('os.path')1341 def patched(mock_path):1342 patch.stopall()1343 self.assertIs(os.path, mock_path)1344 self.assertIs(os.unlink, unlink)1345 self.assertIs(os.chdir, chdir)1346 patched()1347 self.assertIs(os.path, path)1348 def test_stopall_lifo(self):1349 stopped = []1350 class thing(object):1351 one = two = three = None1352 def get_patch(attribute):1353 class mypatch(_patch):1354 def stop(self):1355 stopped.append(attribute)1356 return super(mypatch, self).stop()1357 return mypatch(lambda: thing, attribute, None, None,1358 False, None, None, None, {})1359 [get_patch(val).start() for val in ("one", "two", "three")]1360 patch.stopall()1361 self.assertEqual(stopped, ["three", "two", "one"])1362 def test_special_attrs(self):1363 def foo(x=0):1364 """TEST"""1365 return x1366 with patch.object(foo, '__defaults__', (1, )):1367 self.assertEqual(foo(), 1)1368 self.assertEqual(foo(), 0)1369 with patch.object(foo, '__doc__', "FUN"):1370 self.assertEqual(foo.__doc__, "FUN")1371 self.assertEqual(foo.__doc__, "TEST")1372 with patch.object(foo, '__module__', "testpatch2"):1373 self.assertEqual(foo.__module__, "testpatch2")...
viewsphere.py
Source:viewsphere.py
1# coding=utf-82"""Class to subdivide the sphere and hemisphere for view-based and radiation studies."""3from __future__ import division4import math5from ladybug_geometry.geometry2d.pointvector import Vector2D6from ladybug_geometry.geometry3d.pointvector import Point3D, Vector3D7from ladybug_geometry.geometry3d.mesh import Mesh3D8class ViewSphere(object):9 """Class for subdividing the sphere and hemisphere for view-based studies.10 Note:11 [1] Tregenza, Peter. (1987). Subdivision of the sky hemisphere for luminance12 measurements. Lighting Research & Technology - LIGHTING RES TECHNOL.13 19. 13-14. 10.1177/096032718701900103.14 Properties:15 * tregenza_dome_vectors16 * tregenza_sphere_vectors17 * tregenza_dome_mesh18 * tregenza_dome_mesh_high_res19 * tregenza_sphere_mesh20 * tregenza_solid_angles21 * reinhart_dome_vectors22 * reinhart_sphere_vectors23 * reinhart_dome_mesh24 * reinhart_sphere_mesh25 * reinhart_solid_angles26 """27 # number of patches in each row of the most-used sky domes28 TREGENZA_PATCHES_PER_ROW = (30, 30, 24, 24, 18, 12, 6)29 REINHART_PATCHES_PER_ROW = (60, 60, 60, 60, 48, 48, 48, 48, 36, 36, 24, 24, 12, 12)30 # number of steradians for the patches of each row of the most-used sky domes31 TREGENZA_COEFFICIENTS = \32 (0.0435449227, 0.0416418006, 0.0473984151, 0.0406730411, 0.0428934136,33 0.0445221864, 0.0455168385, 0.0344199465)34 REINHART_COEFFICIENTS = \35 (0.0113221971, 0.0111894547, 0.0109255262, 0.0105335058, 0.0125224872,36 0.0117312774, 0.0108025291, 0.00974713106, 0.011436609, 0.00974295956,37 0.0119026242, 0.00905126163, 0.0121875626, 0.00612971396, 0.00921483254)38 __slots__ = ('_tregenza_dome_vectors', '_tregenza_sphere_vectors',39 '_tregenza_dome_mesh', '_tregenza_dome_mesh_high_res',40 '_tregenza_sphere_mesh', '_tregenza_solid_angles',41 '_reinhart_dome_vectors', '_reinhart_sphere_vectors',42 '_reinhart_dome_mesh', '_reinhart_sphere_mesh',43 '_reinhart_solid_angles')44 def __init__(self):45 """Create the ViewSphere."""46 # everything starts with None and properties are generated as requested47 self._tregenza_dome_vectors = None48 self._tregenza_sphere_vectors = None49 self._tregenza_dome_mesh = None50 self._tregenza_dome_mesh_high_res = None51 self._tregenza_sphere_mesh = None52 self._tregenza_solid_angles = None53 self._reinhart_dome_vectors = None54 self._reinhart_sphere_vectors = None55 self._reinhart_dome_mesh = None56 self._reinhart_sphere_mesh = None57 self._reinhart_solid_angles = None58 @property59 def tregenza_dome_vectors(self):60 """An array of 145 vectors representing the Tregenza sky dome."""61 if self._tregenza_dome_vectors is None:62 self._tregenza_dome_mesh, self._tregenza_dome_vectors = self.dome_patches()63 return self._tregenza_dome_vectors64 @property65 def tregenza_sphere_vectors(self):66 """An array of 290 vectors representing a sphere of Tregenza vectors."""67 if self._tregenza_sphere_vectors is None:68 self._tregenza_sphere_mesh, self._tregenza_sphere_vectors = \69 self.sphere_patches()70 return self._tregenza_sphere_vectors71 @property72 def tregenza_dome_mesh(self):73 """An Mesh3D representing the Tregenza sky dome.74 There is one quad face per patch except for the last circular patch, which75 is represented by 6 triangles.76 """77 if self._tregenza_dome_mesh is None:78 self._tregenza_dome_mesh, self._tregenza_dome_vectors = self.dome_patches()79 return self._tregenza_dome_mesh80 @property81 def tregenza_dome_mesh_high_res(self):82 """An high-resolution Mesh3D representing the Tregenza sky dome.83 Each patch is represented by a 3x3 set of quad faces except for the last84 circular patch, which is represented by 18 triangles.85 """86 if self._tregenza_dome_mesh_high_res is None:87 self._tregenza_dome_mesh_high_res, _ = self.dome_patches(3, True)88 return self._tregenza_dome_mesh_high_res89 @property90 def tregenza_sphere_mesh(self):91 """An Mesh3D representing a Tregenza sphere.92 There is one quad face per patch except for the two circular patches, which93 are each represented by 6 triangles.94 """95 if self._tregenza_sphere_mesh is None:96 self._tregenza_sphere_mesh, self._tregenza_sphere_vectors = \97 self.sphere_patches()98 return self._tregenza_sphere_mesh99 @property100 def tregenza_solid_angles(self):101 """Get a list of solid angles that align with the tregenza_dome_vectors."""102 if self._reinhart_solid_angles is None:103 angles = view_sphere.TREGENZA_COEFFICIENTS104 patch_rows = view_sphere.TREGENZA_PATCHES_PER_ROW + (1,)105 patch_angles = []106 for ang, p_count in zip(angles, patch_rows):107 patch_angles.extend([ang] * p_count)108 self._reinhart_solid_angles = tuple(patch_angles)109 return self._reinhart_solid_angles110 @property111 def reinhart_dome_vectors(self):112 """An array of 577 vectors representing the Reinhart sky dome."""113 if self._reinhart_dome_vectors is None:114 self._reinhart_dome_mesh, self._reinhart_dome_vectors = self.dome_patches(2)115 return self._reinhart_dome_vectors116 @property117 def reinhart_sphere_vectors(self):118 """An array of 1154 vectors representing a sphere of Reinhart vectors."""119 if self._reinhart_sphere_vectors is None:120 self._reinhart_sphere_mesh, self._reinhart_sphere_vectors = \121 self.sphere_patches(2)122 return self._reinhart_sphere_vectors123 @property124 def reinhart_dome_mesh(self):125 """An Mesh3D representing the Reinhart sky dome.126 There is one quad face per patch except for the last circular patch, which127 is represented by 12 triangles.128 """129 if self._reinhart_dome_mesh is None:130 self._reinhart_dome_mesh, self._reinhart_dome_vectors = self.dome_patches(2)131 return self._reinhart_dome_mesh132 @property133 def reinhart_sphere_mesh(self):134 """An Mesh3D representing a Reinhart sphere.135 There is one quad face per patch except for the two circular patches, which136 are each represented by 12 triangles.137 """138 if self._reinhart_sphere_mesh is None:139 self._reinhart_sphere_mesh, self._reinhart_sphere_vectors = \140 self.sphere_patches(2)141 return self._reinhart_sphere_mesh142 @property143 def reinhart_solid_angles(self):144 """Get a list of solid angles that align with the reinhart_dome_vectors."""145 if self._reinhart_solid_angles is None:146 angles = view_sphere.REINHART_COEFFICIENTS147 patch_rows = view_sphere.REINHART_PATCHES_PER_ROW + (1,)148 patch_angles = []149 for ang, p_count in zip(angles, patch_rows):150 patch_angles.extend([ang] * p_count)151 self._reinhart_solid_angles = tuple(patch_angles)152 return self._reinhart_solid_angles153 def horizontal_radial_vectors(self, vector_count):154 """Get perfectly horizontal Vector3Ds radiating outward in a circle.155 Args:156 vector_count: An integer for the number of vectors to generate in the157 horizontal plane. This can align with any of the dome or sphere158 patches by setting this to 30 * division_count.159 Returns:160 A list of ladybug_geometry horizontal Vector3D radiating outward in161 a circle. All vectors are unit vectors.162 """163 base_vec = Vector3D(0, 1, 0)164 horiz_angle = -2 * math.pi / vector_count165 return tuple(base_vec.rotate_xy(horiz_angle * i) for i in range(vector_count))166 def horizontal_radial_patches(self, offset_angle=30, division_count=1,167 subdivide_in_place=False):168 """Get Vector3Ds within a certain angle offset from the horizontal plane.169 Args:170 offset_angle: A number between 0 and 90 for the angle offset from the171 horizontal plane at which vectors will be included. Vectors both172 above and below this angle will be included (Default: 30 for the173 rough vertical limit of human peripheral vision).174 division_count: A positive integer for the number of times that the175 original Tregenza patches are subdivided. 1 indicates that the176 original Tregenza patches will be used, 2 indicates177 the Reinhart patches will be used, and so on. (Default: 1).178 subdivide_in_place: A boolean to note whether patches should be179 subdivided according to the extension of Tregenza's original180 logic through the Reinhart method (False) or they should be181 simply divided into 4 in place (True).182 Returns:183 A tuple with two elements184 - patch_mesh: A ladybug_geometry Mesh3D that represents the patches at185 the input division_count. There is one quad face per patch.186 - patch_vectors: A list of ladybug_geometry Vector3D with one vector187 per patch. These will align with the faces of the patch_mesh.188 All vectors are unit vectors.189 """190 # figure out how many rows and patches should be in the output191 patch_row_count = self._patch_row_count_array(division_count)192 patch_count = self._patch_count_in_radial_offset(193 offset_angle, division_count, patch_row_count, subdivide_in_place)194 # get the dome and vectors and remove faces up tot the patch count195 m_all, v_all = self.dome_patches(division_count, subdivide_in_place)196 pattern = [True] * patch_count + \197 [False] * (sum(patch_row_count) - patch_count + 6 * division_count)198 m_top, _ = m_all.remove_faces(pattern)199 v_top = tuple(vec for vec, val in zip(v_all, pattern) if val)200 # reverse the vectors and negate all the z values of the sky patch mesh201 return self._generate_bottom_from_top(m_top, v_top)202 def horizontal_radial_patch_weights(self, offset_angle=30, division_count=1):203 """Get a list of numbers corresponding to the area weight of each radial patch.204 Args:205 offset_angle: A number between 0 and 90 for the angle offset from the206 horizontal plane at which vectors will be included. Vectors both207 above and below this angle will be included (Default: 30).208 division_count: A positive integer for the number of times that the209 original Tregenza patches are subdivided. (Default: 1).210 Returns:211 A list of numbers with a value for each patch that corresponds to the212 area of that patch. The aveage value of all the patches is equal to 1.213 """214 # get the areas of the patches and the number of patches to include in the offset215 patch_areas, patch_row_count = self._dome_patch_areas(division_count)216 patch_count = self._patch_count_in_radial_offset(217 offset_angle, division_count, patch_row_count)218 # normalize the patch areas so that they average to 1219 relevant_patches = patch_areas[:patch_count]220 avg_patch_area = sum(relevant_patches) / len(relevant_patches)221 return [p_area / avg_patch_area for p_area in relevant_patches] * 2222 def dome_patches(self, division_count=1, subdivide_in_place=False):223 """Get Vector3Ds and a correcponding Mesh3D for a dome.224 Args:225 division_count: A positive integer for the number of times that the226 original Tregenza patches are subdivided. 1 indicates that the227 original Tregenza patches will be used, 2 indicates228 the Reinhart patches will be used, and so on. (Default: 1).229 subdivide_in_place: A boolean to note whether patches should be230 subdivided according to the extension of Tregenza's original231 logic through the Reinhart method (False) or they should be232 simply divided into 4 in place (True). The latter is useful233 for making higher resolution Mesh visualizations of an234 inherently low-resolution dome.235 Returns:236 A tuple with two elements237 - patch_mesh: A ladybug_geometry Mesh3D that represents the dome at238 the input division_count. There is one quad face per patch except239 for the last circular patch, which is represented by a number of240 triangles equal to division_count * 6.241 - patch_vectors: A list of ladybug_geometry Vector3D with one vector242 per patch. These will align with the faces of the patch_mesh up243 until the last circular patch, which will have a single vector244 for the several triangular faces. All vectors are unit vectors.245 """246 # compute constants to be used in the generation of patch points247 patch_row_count = self._patch_row_count_array(division_count)248 base_vec = Vector3D(0, 1, 0)249 rotate_axis = Vector3D(1, 0, 0)250 vertical_angle = math.pi / (2 * len(patch_row_count) + division_count) if \251 subdivide_in_place else math.pi / (2 * len(patch_row_count) + 1)252 # loop through the patch values and generate points for each vertex253 vertices, faces = [], []254 pt_i = -2 # track the number of vertices in the mesh255 for row_i, row_count in enumerate(patch_row_count):256 pt_i += 2 # advance the number of vertices by two257 horiz_angle = -2 * math.pi / row_count # horizontal angle of each patch258 vec01 = base_vec.rotate(rotate_axis, vertical_angle * row_i)259 vec02 = vec01.rotate(rotate_axis, vertical_angle)260 correction_angle = -horiz_angle / 2261 if subdivide_in_place:262 correction_angle * division_count263 vec1 = vec01.rotate_xy(correction_angle)264 vec2 = vec02.rotate_xy(correction_angle)265 vertices.extend((Point3D(v.x, v.y, v.z) for v in (vec1, vec2)))266 for _ in range(row_count): # generate the row of patches267 vec3 = vec1.rotate_xy(horiz_angle)268 vec4 = vec2.rotate_xy(horiz_angle)269 vertices.extend((Point3D(v.x, v.y, v.z) for v in (vec3, vec4)))270 faces.append((pt_i, pt_i + 1, pt_i + 3, pt_i + 2))271 pt_i += 2 # advance the number of vertices by two272 vec1, vec2 = vec3, vec4 # reset vec1 and vec2 for the next patch273 # add triangular faces to represent the last circular patch274 end_vert_i = len(vertices)275 start_vert_i = len(vertices) - patch_row_count[-1] * 2 - 1276 vertices.append(Point3D(0, 0, 1))277 for tr_i in range(0, patch_row_count[-1] * 2, 2):278 faces.append((start_vert_i + tr_i, end_vert_i, start_vert_i + tr_i + 2))279 # create the Mesh3D object and derive the patch vectors from the mesh280 patch_mesh = Mesh3D(vertices, faces)281 patch_vectors = patch_mesh.face_normals[:-patch_row_count[-1]] + \282 (Vector3D(0, 0, 1),)283 return patch_mesh, patch_vectors284 def dome_patch_weights(self, division_count=1):285 """Get a list of numbers corresponding to the area weight of each dome patch.286 Args:287 division_count: A positive integer for the number of times that the288 original Tregenza patches are subdivided. (Default: 1).289 Returns:290 A list of numbers with a value for each patch that corresponds to the291 area of that patch. The aveage value of all the patches is equal to 1.292 """293 # get the areas of the patches294 patch_areas, _ = self._dome_patch_areas(division_count)295 # normalize the patch areas so that they average to 1296 avg_patch_area = 2 * math.pi / len(patch_areas)297 return [p_area / avg_patch_area for p_area in patch_areas]298 def sphere_patches(self, division_count=1, subdivide_in_place=False):299 """Get Vector3Ds and a correcponding Mesh3D for a sphere.300 Args:301 division_count: A positive integer for the number of times that the302 original Tregenza patches are subdivided. 1 indicates that the303 original Tregenza patches will be used, 2 indicates304 the Reinhart patches will be used, and so on. (Default: 1).305 subdivide_in_place: A boolean to note whether patches should be306 subdivided according to the extension of Tregenza's original307 logic through the Reinhart method (False) or they should be308 simply divided into 4 in place (True). The latter is useful309 for making higher resolution Mesh visualizations of an310 inherently low-resolution dome.311 Returns:312 A tuple with two elements313 - patch_mesh: A ladybug_geometry Mesh3D that represents the sphere at314 the input division_count. There is one quad face per patch except315 for the last circular patch of each hemisphere, which is represented316 by a number of triangles equal to division_count * 6.317 - patch_vectors: A list of ladybug_geometry Vector3D with one vector318 per patch. These will align with the faces of the patch_mesh except319 for the two circular patches, which will have a single vector320 for the several triangular faces. All vectors are unit vectors.321 """322 # generate patches for the hemisphere323 m_top, v_top = self.dome_patches(division_count, subdivide_in_place)324 # reverse the vectors and negate all the z values of the sky patch mesh325 return self._generate_bottom_from_top(m_top, v_top)326 def sphere_patch_weights(self, division_count=1):327 """Get a list of numbers corresponding to the area weight of each sphere patch.328 Args:329 division_count: A positive integer for the number of times that the330 original Tregenza patches are subdivided. (Default: 1).331 Returns:332 A list of numbers with a value for each patch that corresponds to the333 area of that patch. The aveage value of all the patches is equal to 1.334 """335 # get the areas of the patches336 patch_areas, _ = self._dome_patch_areas(division_count)337 # normalize the patch areas so that they average to 1338 avg_patch_area = 2 * math.pi / len(patch_areas)339 return [p_area / avg_patch_area for p_area in patch_areas] * 2340 def dome_radial_patches(self, azimuth_count=72, altitude_count=18):341 """Get Vector3Ds and a correcponding Mesh3D for a a radial dome.342 Args:343 azimuth_count: A positive integer for the number of times that344 the horizontal circle will be subdivided into azimuth345 patches. (Default: 72).346 altitude_count: A positive integer for the number of times that347 the dome quarter-circle will be subdivided into altitude348 patches. (Default: 18).349 Returns:350 A tuple with two elements351 - patch_mesh: A ladybug_geometry Mesh3D that represents the patches at352 the input azimuth_count and altitude_count.353 - patch_vectors: A list of ladybug_geometry Vector3D with one vector354 per mesh face. These will align with the faces of the patch_mesh.355 All vectors are unit vectors.356 """357 # set up starting vectors and points358 base_vec, rotate_axis = Vector3D(0, 1, 0), Vector3D(1, 0, 0)359 horiz_angle = -2 * math.pi / azimuth_count360 vertical_angle = math.pi / (2 * altitude_count)361 # loop through the patch values and generate points for each vertex362 vertices, faces = [], []363 pt_i = -2 # track the number of vertices in the mesh364 for row_i in range(altitude_count - 1):365 pt_i += 2 # advance the number of vertices by two366 vec1 = base_vec.rotate(rotate_axis, vertical_angle * row_i)367 vec2 = vec1.rotate(rotate_axis, vertical_angle)368 vertices.extend((Point3D(v.x, v.y, v.z) for v in (vec1, vec2)))369 for _ in range(azimuth_count): # generate the row of patches370 vec3 = vec1.rotate_xy(horiz_angle)371 vec4 = vec2.rotate_xy(horiz_angle)372 vertices.extend((Point3D(v.x, v.y, v.z) for v in (vec3, vec4)))373 faces.append((pt_i, pt_i + 1, pt_i + 3, pt_i + 2))374 pt_i += 2 # advance the number of vertices by two375 vec1, vec2 = vec3, vec4 # reset vec1 and vec2 for the next patch376 # add triangular faces to represent the last circular patch377 end_vert_i = len(vertices)378 start_vert_i = len(vertices) - azimuth_count * 2 - 1379 vertices.append(Point3D(0, 0, 1))380 for tr_i in range(0, azimuth_count * 2, 2):381 faces.append((start_vert_i + tr_i, end_vert_i, start_vert_i + tr_i + 2))382 # create the Mesh3D object and derive the patch vectors from the mesh383 patch_mesh = Mesh3D(vertices, faces)384 patch_vectors = patch_mesh.face_normals385 return patch_mesh, patch_vectors386 def dome_radial_patch_weights(self, azimuth_count=72, altitude_count=18):387 """Get a list of numbers corresponding to the area weight of each dome patch.388 Args:389 azimuth_count: A positive integer for the number of times that390 the horizontal circle will be subdivided into azimuth391 patches. (Default: 72).392 altitude_count: A positive integer for the number of times that393 the dome quarter-circle will be subdivided into altitude394 patches. (Default: 18).395 Returns:396 A list of numbers with a value for each patch that corresponds to the397 area of that patch. The aveage value of all the patches is equal to 1.398 """399 # get the areas of the patches400 patch_areas = self._dome_radial_patch_areas(azimuth_count, altitude_count)401 # normalize the patch areas so that they average to 1402 total_patch_area = 2 * math.pi403 return [p_area / total_patch_area for p_area in patch_areas]404 @staticmethod405 def orientation_pattern(plane_normal, view_vectors):406 """Get booleans for whether view vectors are blocked by a plane.407 Args:408 plane_normal: A Vector3D for the normal of the plane.409 view_vectors: A list of view vectors which will be evaluated to determine410 if they are blocked by the plane or not.411 Returns:412 A tuple with two values.413 - mask_pattern -- A list of booleans for whether each of the view414 vectors are blocked by the plane (True) or not (False).415 - angles -- A list of angles in radians for the angle between the416 plane normal and each view vector.417 """418 mask_pattern, angles, max_angle = [], [], math.pi / 2419 for vec in view_vectors:420 ang = vec.angle(plane_normal)421 angles.append(ang)422 mask_pattern.append(ang > max_angle)423 return mask_pattern, angles424 @staticmethod425 def overhang_pattern(plane_normal, overhang_angle, view_vectors):426 """Get booleans for whether a view vectors are blocked by a overhang.427 Args:428 plane_normal: A Vector3D for the normal of the plane.429 overhang_angle: A number between 0 and 90 for the projection angle430 of an overhang in degrees.431 view_vectors: A list of view vectors which will be evaluated to432 determine if they are blocked by the plane or not.433 Returns:434 A list of booleans for whether each of the view vectors are blocked by435 the overhang (True) or not (False).436 """437 overhang_norm = plane_normal.reverse()438 rotation_axis = overhang_norm.rotate_xy(-math.pi / 2)439 rotation_axis = Vector3D(rotation_axis.x, rotation_axis.y, 0)440 overhang_norm = overhang_norm.rotate(rotation_axis, math.radians(overhang_angle))441 max_angle = math.pi / 2442 return [vec.angle(overhang_norm) < max_angle for vec in view_vectors]443 @staticmethod444 def fin_pattern(plane_normal, left_fin_angle, right_fin_angle, view_vectors):445 """Get booleans for whether a view vectors are blocked by left and right fins.446 Args:447 plane_normal: A Vector3D for the normal of the plane.448 left_fin_angle: A number between 0 and 90 for the projection angle of a449 fin on the left side in degrees.450 right_fin_angle: A number between 0 and 90 for the projection angle of a451 fin on the right side in degrees.452 view_vectors: A list of view vectors which will be evaluated to determine453 if they are blocked by the plane or not.454 Returns:455 A list of booleans for whether each of the view vectors are blocked by456 the fins (True) or not (False).457 """458 # get the min and max angles for the area not blocked by fins459 y_axis, norm_2d = Vector2D(0, 1), Vector2D(plane_normal.x, plane_normal.y)460 srf_angle = math.degrees(norm_2d.angle_clockwise(y_axis))461 angle_min = srf_angle - 90 + right_fin_angle \462 if right_fin_angle else srf_angle - 90463 angle_max = srf_angle + 90 - left_fin_angle \464 if left_fin_angle else srf_angle + 90465 if angle_max > 360:466 angle_max, angle_min = angle_max - 360, angle_min - 360467 if angle_max < 0:468 angle_max, angle_min = angle_max + 360, angle_min + 360469 # evaluate the view_vectors in relation to the min and max angle470 mask_pattern = []471 for vec in view_vectors:472 ang = math.degrees(Vector2D(vec.x, vec.y).angle_clockwise(y_axis))473 is_visible = (ang < angle_max and ang > angle_min) if angle_min > 0 else \474 (ang < angle_max or ang > angle_min + 360)475 mask_pattern.append(not is_visible)476 return mask_pattern477 @staticmethod478 def _dome_radial_patch_areas(azimuth_count=72, altitude_count=18):479 """Get the area of each patch in a radial dome."""480 # get the areas of each spherical cap moving up the unit dome481 vert_angle = math.pi / (2 * altitude_count)482 cap_areas = [2 * math.pi]483 current_angle = vert_angle484 for i in range(altitude_count):485 cap_areas.append(2 * math.pi * (1 - math.sin(current_angle)))486 current_angle += vert_angle487 # get the area of each row and subdivide it by the patch count of the row488 row_areas = [cap_areas[i] - cap_areas[i + 1] for i in range(len(cap_areas) - 1)]489 patch_areas = []490 for row_area in row_areas:491 patch_areas.extend([row_area / azimuth_count] * azimuth_count)492 return patch_areas493 @staticmethod494 def _dome_patch_areas(division_count):495 """Get the area of each patch in a dome from a division_count."""496 # get the areas of each spherical cap moving up the unit dome497 patch_row_count = ViewSphere._patch_row_count_array(division_count)498 vert_angle = math.pi / (2 * len(patch_row_count) + division_count)499 cap_areas = [2 * math.pi]500 current_angle = vert_angle501 for i in range(len(patch_row_count)):502 cap_areas.append(2 * math.pi * (1 - math.sin(current_angle)))503 current_angle += vert_angle504 # get the area of each row and subdivide it by the patch count of the row505 row_areas = [cap_areas[i] - cap_areas[i + 1] for i in range(len(cap_areas) - 1)]506 patch_areas = []507 for row_count, row_area in zip(patch_row_count, row_areas):508 patch_areas.extend([row_area / row_count] * row_count)509 patch_areas.append(cap_areas[-1])510 return patch_areas, patch_row_count511 @staticmethod512 def _patch_count_in_radial_offset(offset_angle, division_count, patch_row_count,513 subdivide_in_place=False):514 """Get the number of patches within a radial offset from the horizontal plane."""515 rad_angle = math.radians(offset_angle)516 patch_rows = len(patch_row_count)517 vert_angle = math.pi / (2 * patch_rows + division_count) if subdivide_in_place \518 else math.pi / (2 * patch_rows + 1)519 row_count = int(round(rad_angle / vert_angle))520 return sum(patch_row_count[:row_count])521 @staticmethod522 def _patch_row_count_array(division_count):523 """Get an array of the number of patches in each dome row from division_count."""524 patch_row_count = ViewSphere.TREGENZA_PATCHES_PER_ROW525 if division_count != 1:526 patch_row_count = [init_ct * division_count for init_ct in patch_row_count527 for i in range(division_count)]528 return patch_row_count529 @staticmethod530 def _generate_bottom_from_top(m_top, v_top):531 """Get a joined mesh and vectors for top and bottom from only top vectors."""532 # reverse the vectors and negate all the z values of the sky patch mesh533 verts = tuple(Point3D(pt.x, pt.y, -pt.z) for pt in m_top.vertices)534 faces = tuple(face[::-1] for face in m_top.faces)535 m_bottom = Mesh3D(verts, faces)536 v_bottom = tuple(Vector3D(v.x, v.y, -v.z) for v in v_top)537 # join everything together538 patch_mesh = Mesh3D.join_meshes([m_top, m_bottom])539 patch_vectors = v_top + v_bottom540 return patch_mesh, patch_vectors541 def __repr__(self):542 """ViewSphere representation."""543 return 'ViewSphere'544# make a single object that can be reused throughout the library...
patch_mixin_tests.js
Source:patch_mixin_tests.js
...34 assert.step('A.f');35 }36 }37 );38 A.patch('patch', T =>39 class extends T {40 constructor() {41 super();42 assert.step('patch.constructor');43 }44 f() {45 super.f();46 assert.step('patch.f');47 }48 }49 );50 (new A()).f();51 assert.verifySteps([52 'A.constructor',53 'patch.constructor',54 'A.f',55 'patch.f',56 ]);57 });58 QUnit.test('two patches on same base class', function (assert) {59 assert.expect(7);60 const A = patchMixin(61 class {62 constructor() {63 assert.step('A.constructor');64 }65 f() {66 assert.step('A.f');67 }68 }69 );70 A.patch('patch1', T =>71 class extends T {72 constructor() {73 super();74 assert.step('patch1.constructor');75 }76 f() {77 super.f();78 assert.step('patch1.f');79 }80 }81 );82 A.patch('patch2', T =>83 class extends T {84 constructor() {85 super();86 assert.step('patch2.constructor');87 }88 f() {89 super.f();90 assert.step('patch2.f');91 }92 }93 );94 (new A()).f();95 assert.verifySteps([96 'A.constructor',97 'patch1.constructor',98 'patch2.constructor',99 'A.f',100 'patch1.f',101 'patch2.f',102 ]);103 });104 QUnit.test('two patches with same name on same base class', function (assert) {105 assert.expect(1);106 const A = patchMixin(class {});107 A.patch('patch', T => class extends T {});108 // keys should be unique109 assert.throws(() => {110 A.patch('patch', T => class extends T {});111 });112 });113 QUnit.test('unpatch', function (assert) {114 assert.expect(8);115 const A = patchMixin(116 class {117 constructor() {118 assert.step('A.constructor');119 }120 f() {121 assert.step('A.f');122 }123 }124 );125 A.patch('patch', T =>126 class extends T {127 constructor() {128 super();129 assert.step('patch.constructor');130 }131 f() {132 super.f();133 assert.step('patch.f');134 }135 }136 );137 (new A()).f();138 assert.verifySteps([139 'A.constructor',140 'patch.constructor',141 'A.f',142 'patch.f',143 ]);144 A.unpatch('patch');145 (new A()).f();146 assert.verifySteps([147 'A.constructor',148 'A.f',149 ]);150 });151 QUnit.test('unpatch 2', function (assert) {152 assert.expect(12);153 const A = patchMixin(154 class {155 constructor() {156 assert.step('A.constructor');157 }158 f() {159 assert.step('A.f');160 }161 }162 );163 A.patch('patch1', T =>164 class extends T {165 constructor() {166 super();167 assert.step('patch1.constructor');168 }169 f() {170 super.f();171 assert.step('patch1.f');172 }173 }174 );175 A.patch('patch2', T =>176 class extends T {177 constructor() {178 super();179 assert.step('patch2.constructor');180 }181 f() {182 super.f();183 assert.step('patch2.f');184 }185 }186 );187 (new A()).f();188 assert.verifySteps([189 'A.constructor',190 'patch1.constructor',191 'patch2.constructor',192 'A.f',193 'patch1.f',194 'patch2.f',195 ]);196 A.unpatch('patch1');197 (new A()).f();198 assert.verifySteps([199 'A.constructor',200 'patch2.constructor',201 'A.f',202 'patch2.f',203 ]);204 });205 QUnit.test('unpatch inexistent', function (assert) {206 assert.expect(1);207 const A = patchMixin(class {});208 A.patch('patch', T => class extends T {});209 A.unpatch('patch');210 assert.throws(() => {211 A.unpatch('inexistent-patch');212 });213 });214 QUnit.test('patch for specialization', function (assert) {215 assert.expect(1);216 let args = [];217 const A = patchMixin(218 class {219 constructor() {220 args = ['A', ...arguments];221 }222 }223 );224 A.patch('patch', T =>225 class extends T {226 constructor() {227 super('patch', ...arguments);228 }229 }230 );231 new A('instantiation');232 assert.deepEqual(args, ['A', 'patch', 'instantiation']);233 });234 QUnit.test('instance fields', function (assert) {235 assert.expect(1);236 const A = patchMixin(237 class {238 constructor() {239 this.x = ['A'];240 }241 }242 );243 A.patch('patch', T =>244 class extends T {245 constructor() {246 super();247 this.x.push('patch');248 }249 }250 );251 const a = new A();252 assert.deepEqual(a.x, ['A', 'patch']);253 });254 QUnit.test('call instance method defined in patch', function (assert) {255 assert.expect(3);256 const A = patchMixin(257 class {}258 );259 assert.notOk((new A()).f);260 A.patch('patch', T =>261 class extends T {262 f() {263 assert.step('patch.f');264 }265 }266 );267 (new A()).f();268 assert.verifySteps(['patch.f']);269 });270 QUnit.test('class methods', function (assert) {271 assert.expect(7);272 const A = patchMixin(273 class {274 static f() {275 assert.step('A');276 }277 }278 );279 A.f();280 assert.verifySteps(['A']);281 A.patch('patch', T =>282 class extends T {283 static f() {284 super.f();285 assert.step('patch');286 }287 }288 );289 A.f();290 assert.verifySteps(['A', 'patch']);291 A.unpatch('patch');292 A.f();293 assert.verifySteps(['A']);294 });295 QUnit.test('class fields', function (assert) {296 assert.expect(4);297 class A {}298 A.foo = ['A'];299 A.bar = 'A';300 const PatchableA = patchMixin(A);301 PatchableA.patch('patch', T => {302 class Patch extends T {}303 Patch.foo = [...T.foo, 'patched A'];304 Patch.bar = 'patched A';305 return Patch;306 });307 assert.deepEqual(PatchableA.foo, ['A', 'patched A']);308 assert.strictEqual(PatchableA.bar, 'patched A');309 PatchableA.unpatch('patch');310 assert.deepEqual(PatchableA.foo, ['A']);311 assert.strictEqual(PatchableA.bar, 'A');312 });313 QUnit.test('lazy patch', function (assert) {314 assert.expect(4);315 const A = patchMixin(316 class {317 constructor() {318 assert.step('A.constructor');319 }320 f() {321 assert.step('A.f');322 }323 }324 );325 const a = new A();326 A.patch('patch', T =>327 class extends T {328 constructor() {329 super();330 // will not be called331 assert.step('patch.constructor');332 }333 f() {334 super.f();335 assert.step('patch.f');336 }337 }338 );339 a.f();340 assert.verifySteps([341 'A.constructor',342 'A.f',343 'patch.f',344 ]);345 });346 QUnit.module('inheritance');347 QUnit.test('inheriting a patchable class', function (assert) {348 assert.expect(8);349 const A = patchMixin(350 class {351 constructor() {352 assert.step('A.constructor');353 }354 f() {355 assert.step('A.f');356 }357 }358 );359 class B extends A {360 constructor() {361 super();362 assert.step('B.constructor');363 }364 f() {365 super.f();366 assert.step('B.f');367 }368 }369 (new A()).f();370 assert.verifySteps([371 'A.constructor',372 'A.f',373 ]);374 (new B()).f();375 assert.verifySteps([376 'A.constructor',377 'B.constructor',378 'A.f',379 'B.f',380 ]);381 });382 QUnit.test('inheriting a patchable class that has patch', function (assert) {383 assert.expect(12);384 const A = patchMixin(385 class {386 constructor() {387 assert.step('A.constructor');388 }389 f() {390 assert.step('A.f');391 }392 }393 );394 A.patch('patch', T =>395 class extends T {396 constructor() {397 super();398 assert.step('patch.constructor');399 }400 f() {401 super.f();402 assert.step('patch.f');403 }404 }405 );406 class B extends A {407 constructor() {408 super();409 assert.step('B.constructor');410 }411 f() {412 super.f();413 assert.step('B.f');414 }415 }416 (new A()).f();417 assert.verifySteps([418 'A.constructor',419 'patch.constructor',420 'A.f',421 'patch.f',422 ]);423 (new B()).f();424 assert.verifySteps([425 'A.constructor',426 'patch.constructor',427 'B.constructor',428 'A.f',429 'patch.f',430 'B.f',431 ]);432 });433 QUnit.test('patch inherited patchable class', function (assert) {434 assert.expect(10);435 const A = patchMixin(436 class {437 constructor() {438 assert.step('A.constructor');439 }440 f() {441 assert.step('A.f');442 }443 }444 );445 const B = patchMixin(446 class extends A {447 constructor() {448 super();449 assert.step('B.constructor');450 }451 f() {452 super.f();453 assert.step('B.f');454 }455 }456 );457 B.patch('patch', T =>458 class extends T {459 constructor() {460 super();461 assert.step('patch.constructor');462 }463 f() {464 super.f();465 assert.step('patch.f');466 }467 }468 );469 (new A()).f();470 assert.verifySteps([471 'A.constructor',472 'A.f',473 ]);474 (new B()).f();475 assert.verifySteps([476 'A.constructor',477 'B.constructor',478 'patch.constructor',479 'A.f',480 'B.f',481 'patch.f',482 ]);483 });484 QUnit.test('patch inherited patched class', function (assert) {485 assert.expect(14);486 const A = patchMixin(487 class {488 constructor() {489 assert.step('A.constructor');490 }491 f() {492 assert.step('A.f');493 }494 }495 );496 A.patch('patch', T =>497 class extends T {498 constructor() {499 super();500 assert.step('A.patch.constructor');501 }502 f() {503 super.f();504 assert.step('A.patch.f');505 }506 }507 );508 /**509 * /!\ WARNING /!\510 *511 * If you want to patch class B, make it patchable512 * otherwise it will patch class A!513 */514 const B = patchMixin(515 class extends A {516 constructor() {517 super();518 assert.step('B.constructor');519 }520 f() {521 super.f();522 assert.step('B.f');523 }524 }525 );526 B.patch('patch', T =>527 class extends T {528 constructor() {529 super();530 assert.step('B.patch.constructor');531 }532 f() {533 super.f();534 assert.step('B.patch.f');535 }536 }537 );538 const a = new A();539 a.f();540 assert.verifySteps([541 'A.constructor',542 'A.patch.constructor',543 'A.f',544 'A.patch.f',545 ]);546 const b = new B();547 b.f();548 assert.verifySteps([549 'A.constructor',550 'A.patch.constructor',551 'B.constructor',552 'B.patch.constructor',553 'A.f',554 'A.patch.f',555 'B.f',556 'B.patch.f',557 ]);558 });559 QUnit.test('unpatch inherited patched class', function (assert) {560 assert.expect(15);561 const A = patchMixin(562 class {563 constructor() {564 assert.step('A.constructor');565 }566 f() {567 assert.step('A.f');568 }569 }570 );571 A.patch('patch', T =>572 class extends T {573 constructor() {574 super();575 assert.step('A.patch.constructor');576 }577 f() {578 super.f();579 assert.step('A.patch.f');580 }581 }582 );583 const B = patchMixin(584 class extends A {585 constructor() {586 super();587 assert.step('B.constructor');588 }589 f() {590 super.f();591 assert.step('B.f');592 }593 }594 );595 B.patch('patch', T =>596 class extends T {597 constructor() {598 super();599 assert.step('B.patch.constructor');600 }601 f() {602 super.f();603 assert.step('B.patch.f');604 }605 }606 );607 A.unpatch('patch');608 (new A()).f();609 assert.verifySteps([610 'A.constructor',611 'A.f',612 ]);613 (new B()).f();614 assert.verifySteps([615 'A.constructor',616 'B.constructor',617 'B.patch.constructor',618 'A.f',619 'B.f',620 'B.patch.f',621 ]);622 B.unpatch('patch');623 (new B()).f();624 assert.verifySteps([625 'A.constructor',626 'B.constructor',627 'A.f',628 'B.f',629 ]);630 });631 QUnit.test('unpatch inherited patched class 2', function (assert) {632 assert.expect(12);633 const A = patchMixin(634 class {635 constructor() {636 assert.step('A.constructor');637 }638 f() {639 assert.step('A.f');640 }641 }642 );643 A.patch('patch', T =>644 class extends T {645 constructor() {646 super();647 assert.step('A.patch.constructor');648 }649 f() {650 super.f();651 assert.step('A.patch.f');652 }653 }654 );655 const B = patchMixin(656 class extends A {657 constructor() {658 super();659 assert.step('B.constructor');660 }661 f() {662 super.f();663 assert.step('B.f');664 }665 }666 );667 B.patch('patch', T =>668 class extends T {669 constructor() {670 super();671 assert.step('B.patch.constructor');672 }673 f() {674 super.f();675 assert.step('B.patch.f');676 }677 }678 );679 B.unpatch('patch');680 (new B()).f();681 assert.verifySteps([682 'A.constructor',683 'A.patch.constructor',684 'B.constructor',685 'A.f',686 'A.patch.f',687 'B.f',688 ]);689 A.unpatch('patch');690 (new B()).f();691 assert.verifySteps([692 'A.constructor',693 'B.constructor',694 'A.f',695 'B.f',696 ]);697 });698 QUnit.test('class methods', function (assert) {699 assert.expect(12);700 const A = patchMixin(701 class {702 static f() {703 assert.step('A');704 }705 }706 );707 const B = patchMixin(708 class extends A {709 static f() {710 super.f();711 assert.step('B');712 }713 }714 );715 A.patch('patch', T =>716 class extends T {717 static f() {718 super.f();719 assert.step('A.patch');720 }721 }722 );723 B.patch('patch', T =>724 class extends T {725 static f() {726 super.f();727 assert.step('B.patch');728 }729 }730 );731 B.f();732 assert.verifySteps(['A', 'A.patch', 'B', 'B.patch']);733 A.unpatch('patch');734 B.f();735 assert.verifySteps(['A', 'B', 'B.patch']);736 B.unpatch('patch');737 B.f();738 assert.verifySteps(['A', 'B']);739 });740 QUnit.test('class fields', function (assert) {741 assert.expect(3);742 class A {}743 A.foo = ['A'];744 A.bar = 'A';745 const PatchableA = patchMixin(A);746 class B extends PatchableA {}747 // /!\ This is not dynamic748 // so if A.foo is patched after this assignment749 // B.foo won't have the patches of A.foo750 B.foo = [...PatchableA.foo, 'B'];751 B.bar = 'B';752 const PatchableB = patchMixin(B);753 PatchableA.patch('patch', T => {754 class Patch extends T {}755 Patch.foo = [...T.foo, 'patched A'];756 Patch.bar = 'patched A';757 return Patch;758 });759 PatchableB.patch('patch', T => {760 class Patch extends T {}761 Patch.foo = [...T.foo, 'patched B'];762 Patch.bar = 'patched B';763 return Patch;764 });765 assert.deepEqual(PatchableB.foo, [ 'A', /* 'patched A', */ 'B', 'patched B' ]);766 assert.deepEqual(PatchableA.foo, [ 'A', 'patched A' ]);767 assert.strictEqual(PatchableB.bar, 'patched B');768 });769 QUnit.test('inheritance and lazy patch', function (assert) {770 assert.expect(6);771 const A = patchMixin(772 class {773 constructor() {774 assert.step('A.constructor');775 }776 f() {777 assert.step('A.f');778 }779 }780 );781 class B extends A {782 constructor() {783 super();784 assert.step('B.constructor');785 }786 f() {787 super.f();788 assert.step('B.f');789 }790 }791 const b = new B();792 A.patch('patch', T =>793 class extends T {794 constructor() {795 super();796 // will not be called797 assert.step('patch.constructor');798 }799 f() {800 super.f();801 assert.step('patch.f');802 }803 }804 );805 b.f();806 assert.verifySteps([807 'A.constructor',808 'B.constructor',809 'A.f',810 'patch.f',811 'B.f',812 ]);813 });814 QUnit.test('patch not patchable class that inherits patchable class', function (assert) {815 assert.expect(1);816 const A = patchMixin(class {});817 class B extends A {}818 // class B is not patchable819 assert.throws(() => {820 B.patch('patch', T => class extends T {});821 });822 });823 });824});...
commitqueuetask_unittest.py
Source:commitqueuetask_unittest.py
...53 def command_failed(self, failure_message, script_error, patch):54 log("command_failed: failure_message='%s' script_error='%s' patch='%s'" % (55 failure_message, script_error, patch.id()))56 return 394757 def refetch_patch(self, patch):58 return patch59 def expected_failures(self):60 return ExpectedFailures()61 def layout_test_results(self):62 return None63 def report_flaky_tests(self, patch, flaky_results, results_archive):64 flaky_tests = [result.filename for result in flaky_results]65 log("report_flaky_tests: patch='%s' flaky_tests='%s' archive='%s'" % (patch.id(), flaky_tests, results_archive.filename))66 def archive_last_layout_test_results(self, patch):67 log("archive_last_layout_test_results: patch='%s'" % patch.id())68 archive = Mock()69 archive.filename = "mock-archive-%s.zip" % patch.id()70 return archive71 def build_style(self):72 return "both"73class FailingTestCommitQueue(MockCommitQueue):74 def __init__(self, error_plan, test_failure_plan):75 MockCommitQueue.__init__(self, error_plan)76 self._test_run_counter = -1 # Special value to indicate tests have never been run.77 self._test_failure_plan = test_failure_plan78 def run_command(self, command):79 if command[0] == "build-and-test":80 self._test_run_counter += 181 MockCommitQueue.run_command(self, command)82 def _mock_test_result(self, testname):83 return test_results.TestResult(testname, [test_failures.FailureTextMismatch()])84 def layout_test_results(self):85 # Doesn't make sense to ask for the layout_test_results until the tests have run at least once.86 assert(self._test_run_counter >= 0)87 failures_for_run = self._test_failure_plan[self._test_run_counter]88 results = LayoutTestResults(map(self._mock_test_result, failures_for_run))89 # This makes the results trustable by ExpectedFailures.90 results.set_failure_limit_count(10)91 return results92# We use GoldenScriptError to make sure that the code under test throws the93# correct (i.e., golden) exception.94class GoldenScriptError(ScriptError):95 pass96class CommitQueueTaskTest(unittest.TestCase):97 def _run_through_task(self, commit_queue, expected_stderr, expected_exception=None, expect_retry=False):98 tool = MockTool(log_executive=True)99 patch = tool.bugs.fetch_attachment(10000)100 task = CommitQueueTask(commit_queue, patch)101 success = OutputCapture().assert_outputs(self, task.run, expected_stderr=expected_stderr, expected_exception=expected_exception)102 if not expected_exception:103 self.assertEqual(success, not expect_retry)104 return task105 def test_success_case(self):106 commit_queue = MockCommitQueue([])107 expected_stderr = """run_webkit_patch: ['clean']108command_passed: success_message='Cleaned working directory' patch='10000'109run_webkit_patch: ['update']110command_passed: success_message='Updated working directory' patch='10000'111run_webkit_patch: ['apply-attachment', '--no-update', '--non-interactive', 10000]112command_passed: success_message='Applied patch' patch='10000'113run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']114command_passed: success_message='Built patch' patch='10000'115run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']116command_passed: success_message='Passed tests' patch='10000'117run_webkit_patch: ['land-attachment', '--force-clean', '--non-interactive', '--parent-command=commit-queue', 10000]118command_passed: success_message='Landed patch' patch='10000'119"""120 self._run_through_task(commit_queue, expected_stderr)121 def test_clean_failure(self):122 commit_queue = MockCommitQueue([123 ScriptError("MOCK clean failure"),124 ])125 expected_stderr = """run_webkit_patch: ['clean']126command_failed: failure_message='Unable to clean working directory' script_error='MOCK clean failure' patch='10000'127"""128 self._run_through_task(commit_queue, expected_stderr, expect_retry=True)129 def test_update_failure(self):130 commit_queue = MockCommitQueue([131 None,132 ScriptError("MOCK update failure"),133 ])134 expected_stderr = """run_webkit_patch: ['clean']135command_passed: success_message='Cleaned working directory' patch='10000'136run_webkit_patch: ['update']137command_failed: failure_message='Unable to update working directory' script_error='MOCK update failure' patch='10000'138"""139 self._run_through_task(commit_queue, expected_stderr, expect_retry=True)140 def test_apply_failure(self):141 commit_queue = MockCommitQueue([142 None,143 None,144 GoldenScriptError("MOCK apply failure"),145 ])146 expected_stderr = """run_webkit_patch: ['clean']147command_passed: success_message='Cleaned working directory' patch='10000'148run_webkit_patch: ['update']149command_passed: success_message='Updated working directory' patch='10000'150run_webkit_patch: ['apply-attachment', '--no-update', '--non-interactive', 10000]151command_failed: failure_message='Patch does not apply' script_error='MOCK apply failure' patch='10000'152"""153 self._run_through_task(commit_queue, expected_stderr, GoldenScriptError)154 def test_build_failure(self):155 commit_queue = MockCommitQueue([156 None,157 None,158 None,159 GoldenScriptError("MOCK build failure"),160 ])161 expected_stderr = """run_webkit_patch: ['clean']162command_passed: success_message='Cleaned working directory' patch='10000'163run_webkit_patch: ['update']164command_passed: success_message='Updated working directory' patch='10000'165run_webkit_patch: ['apply-attachment', '--no-update', '--non-interactive', 10000]166command_passed: success_message='Applied patch' patch='10000'167run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']168command_failed: failure_message='Patch does not build' script_error='MOCK build failure' patch='10000'169run_webkit_patch: ['build', '--force-clean', '--no-update', '--build-style=both']170command_passed: success_message='Able to build without patch' patch='10000'171"""172 self._run_through_task(commit_queue, expected_stderr, GoldenScriptError)173 def test_red_build_failure(self):174 commit_queue = MockCommitQueue([175 None,176 None,177 None,178 ScriptError("MOCK build failure"),179 ScriptError("MOCK clean build failure"),180 ])181 expected_stderr = """run_webkit_patch: ['clean']182command_passed: success_message='Cleaned working directory' patch='10000'183run_webkit_patch: ['update']184command_passed: success_message='Updated working directory' patch='10000'185run_webkit_patch: ['apply-attachment', '--no-update', '--non-interactive', 10000]186command_passed: success_message='Applied patch' patch='10000'187run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']188command_failed: failure_message='Patch does not build' script_error='MOCK build failure' patch='10000'189run_webkit_patch: ['build', '--force-clean', '--no-update', '--build-style=both']190command_failed: failure_message='Unable to build without patch' script_error='MOCK clean build failure' patch='10000'191"""192 self._run_through_task(commit_queue, expected_stderr, expect_retry=True)193 def test_flaky_test_failure(self):194 commit_queue = MockCommitQueue([195 None,196 None,197 None,198 None,199 ScriptError("MOCK tests failure"),200 ])201 # CommitQueueTask will only report flaky tests if we successfully parsed202 # results.html and returned a LayoutTestResults object, so we fake one.203 commit_queue.layout_test_results = lambda: LayoutTestResults([])204 expected_stderr = """run_webkit_patch: ['clean']205command_passed: success_message='Cleaned working directory' patch='10000'206run_webkit_patch: ['update']207command_passed: success_message='Updated working directory' patch='10000'208run_webkit_patch: ['apply-attachment', '--no-update', '--non-interactive', 10000]209command_passed: success_message='Applied patch' patch='10000'210run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']211command_passed: success_message='Built patch' patch='10000'212run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']213command_failed: failure_message='Patch does not pass tests' script_error='MOCK tests failure' patch='10000'214archive_last_layout_test_results: patch='10000'215run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']216command_passed: success_message='Passed tests' patch='10000'217report_flaky_tests: patch='10000' flaky_tests='[]' archive='mock-archive-10000.zip'218run_webkit_patch: ['land-attachment', '--force-clean', '--non-interactive', '--parent-command=commit-queue', 10000]219command_passed: success_message='Landed patch' patch='10000'220"""221 self._run_through_task(commit_queue, expected_stderr)222 def test_failed_archive(self):223 commit_queue = MockCommitQueue([224 None,225 None,226 None,227 None,228 ScriptError("MOCK tests failure"),229 ])230 commit_queue.layout_test_results = lambda: LayoutTestResults([])231 # It's possible delegate to fail to archive layout tests, don't try to report232 # flaky tests when that happens.233 commit_queue.archive_last_layout_test_results = lambda patch: None234 expected_stderr = """run_webkit_patch: ['clean']235command_passed: success_message='Cleaned working directory' patch='10000'236run_webkit_patch: ['update']237command_passed: success_message='Updated working directory' patch='10000'238run_webkit_patch: ['apply-attachment', '--no-update', '--non-interactive', 10000]239command_passed: success_message='Applied patch' patch='10000'240run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']241command_passed: success_message='Built patch' patch='10000'242run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']243command_failed: failure_message='Patch does not pass tests' script_error='MOCK tests failure' patch='10000'244run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']245command_passed: success_message='Passed tests' patch='10000'246run_webkit_patch: ['land-attachment', '--force-clean', '--non-interactive', '--parent-command=commit-queue', 10000]247command_passed: success_message='Landed patch' patch='10000'248"""249 self._run_through_task(commit_queue, expected_stderr)250 def test_double_flaky_test_failure(self):251 commit_queue = FailingTestCommitQueue([252 None,253 None,254 None,255 None,256 ScriptError("MOCK test failure"),257 ScriptError("MOCK test failure again"),258 ], [259 "foo.html",260 "bar.html",261 "foo.html",262 ])263 # The (subtle) point of this test is that report_flaky_tests does not appear264 # in the expected_stderr for this run.265 # Note also that there is no attempt to run the tests w/o the patch.266 expected_stderr = """run_webkit_patch: ['clean']267command_passed: success_message='Cleaned working directory' patch='10000'268run_webkit_patch: ['update']269command_passed: success_message='Updated working directory' patch='10000'270run_webkit_patch: ['apply-attachment', '--no-update', '--non-interactive', 10000]271command_passed: success_message='Applied patch' patch='10000'272run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']273command_passed: success_message='Built patch' patch='10000'274run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']275command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure' patch='10000'276archive_last_layout_test_results: patch='10000'277run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']278command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure again' patch='10000'279"""280 tool = MockTool(log_executive=True)281 patch = tool.bugs.fetch_attachment(10000)282 task = CommitQueueTask(commit_queue, patch)283 success = OutputCapture().assert_outputs(self, task.run, expected_stderr=expected_stderr)284 self.assertEqual(success, False)285 def test_test_failure(self):286 commit_queue = MockCommitQueue([287 None,288 None,289 None,290 None,291 GoldenScriptError("MOCK test failure"),292 ScriptError("MOCK test failure again"),293 ])294 expected_stderr = """run_webkit_patch: ['clean']295command_passed: success_message='Cleaned working directory' patch='10000'296run_webkit_patch: ['update']297command_passed: success_message='Updated working directory' patch='10000'298run_webkit_patch: ['apply-attachment', '--no-update', '--non-interactive', 10000]299command_passed: success_message='Applied patch' patch='10000'300run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']301command_passed: success_message='Built patch' patch='10000'302run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']303command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure' patch='10000'304archive_last_layout_test_results: patch='10000'305run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']306command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure again' patch='10000'307archive_last_layout_test_results: patch='10000'308run_webkit_patch: ['build-and-test', '--force-clean', '--no-update', '--build', '--test', '--non-interactive']309command_passed: success_message='Able to pass tests without patch' patch='10000'310"""311 self._run_through_task(commit_queue, expected_stderr, GoldenScriptError)312 def test_red_test_failure(self):313 commit_queue = FailingTestCommitQueue([314 None,315 None,316 None,317 None,318 ScriptError("MOCK test failure"),319 ScriptError("MOCK test failure again"),320 ScriptError("MOCK clean test failure"),321 ], [322 "foo.html",323 "foo.html",324 "foo.html",325 ])326 # Tests always fail, and always return the same results, but we327 # should still be able to land in this case!328 expected_stderr = """run_webkit_patch: ['clean']329command_passed: success_message='Cleaned working directory' patch='10000'330run_webkit_patch: ['update']331command_passed: success_message='Updated working directory' patch='10000'332run_webkit_patch: ['apply-attachment', '--no-update', '--non-interactive', 10000]333command_passed: success_message='Applied patch' patch='10000'334run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']335command_passed: success_message='Built patch' patch='10000'336run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']337command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure' patch='10000'338archive_last_layout_test_results: patch='10000'339run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']340command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure again' patch='10000'341archive_last_layout_test_results: patch='10000'342run_webkit_patch: ['build-and-test', '--force-clean', '--no-update', '--build', '--test', '--non-interactive']343command_failed: failure_message='Unable to pass tests without patch (tree is red?)' script_error='MOCK clean test failure' patch='10000'344run_webkit_patch: ['land-attachment', '--force-clean', '--non-interactive', '--parent-command=commit-queue', 10000]345command_passed: success_message='Landed patch' patch='10000'346"""347 self._run_through_task(commit_queue, expected_stderr)348 def test_very_red_tree_retry(self):349 lots_of_failing_tests = map(lambda num: "test-%s.html" % num, range(0, 100))350 commit_queue = FailingTestCommitQueue([351 None,352 None,353 None,354 None,355 ScriptError("MOCK test failure"),356 ScriptError("MOCK test failure again"),357 ScriptError("MOCK clean test failure"),358 ], [359 lots_of_failing_tests,360 lots_of_failing_tests,361 lots_of_failing_tests,362 ])363 # Tests always fail, and return so many failures that we do not364 # trust the results (see ExpectedFailures._can_trust_results) so we365 # just give up and retry the patch.366 expected_stderr = """run_webkit_patch: ['clean']367command_passed: success_message='Cleaned working directory' patch='10000'368run_webkit_patch: ['update']369command_passed: success_message='Updated working directory' patch='10000'370run_webkit_patch: ['apply-attachment', '--no-update', '--non-interactive', 10000]371command_passed: success_message='Applied patch' patch='10000'372run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']373command_passed: success_message='Built patch' patch='10000'374run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']375command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure' patch='10000'376archive_last_layout_test_results: patch='10000'377run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']378command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure again' patch='10000'379archive_last_layout_test_results: patch='10000'380run_webkit_patch: ['build-and-test', '--force-clean', '--no-update', '--build', '--test', '--non-interactive']381command_failed: failure_message='Unable to pass tests without patch (tree is red?)' script_error='MOCK clean test failure' patch='10000'382"""383 self._run_through_task(commit_queue, expected_stderr, expect_retry=True)384 def test_red_tree_patch_rejection(self):385 commit_queue = FailingTestCommitQueue([386 None,387 None,388 None,389 None,390 GoldenScriptError("MOCK test failure"),391 ScriptError("MOCK test failure again"),392 ScriptError("MOCK clean test failure"),393 ], [394 ["foo.html", "bar.html"],395 ["foo.html", "bar.html"],396 ["foo.html"],397 ])398 # Tests always fail, but the clean tree only fails one test399 # while the patch fails two. So we should reject the patch!400 expected_stderr = """run_webkit_patch: ['clean']401command_passed: success_message='Cleaned working directory' patch='10000'402run_webkit_patch: ['update']403command_passed: success_message='Updated working directory' patch='10000'404run_webkit_patch: ['apply-attachment', '--no-update', '--non-interactive', 10000]405command_passed: success_message='Applied patch' patch='10000'406run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']407command_passed: success_message='Built patch' patch='10000'408run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']409command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure' patch='10000'410archive_last_layout_test_results: patch='10000'411run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']412command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure again' patch='10000'413archive_last_layout_test_results: patch='10000'414run_webkit_patch: ['build-and-test', '--force-clean', '--no-update', '--build', '--test', '--non-interactive']415command_failed: failure_message='Unable to pass tests without patch (tree is red?)' script_error='MOCK clean test failure' patch='10000'416"""417 task = self._run_through_task(commit_queue, expected_stderr, GoldenScriptError)418 self.assertEqual(task.results_from_patch_test_run(task._patch).failing_tests(), ["foo.html", "bar.html"])419 def test_land_failure(self):420 commit_queue = MockCommitQueue([421 None,422 None,423 None,424 None,425 None,426 GoldenScriptError("MOCK land failure"),427 ])428 expected_stderr = """run_webkit_patch: ['clean']429command_passed: success_message='Cleaned working directory' patch='10000'430run_webkit_patch: ['update']431command_passed: success_message='Updated working directory' patch='10000'432run_webkit_patch: ['apply-attachment', '--no-update', '--non-interactive', 10000]433command_passed: success_message='Applied patch' patch='10000'434run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']435command_passed: success_message='Built patch' patch='10000'436run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']437command_passed: success_message='Passed tests' patch='10000'438run_webkit_patch: ['land-attachment', '--force-clean', '--non-interactive', '--parent-command=commit-queue', 10000]439command_failed: failure_message='Unable to land patch' script_error='MOCK land failure' patch='10000'440"""441 # FIXME: This should really be expect_retry=True for a better user experiance.442 self._run_through_task(commit_queue, expected_stderr, GoldenScriptError)443 def _expect_validate(self, patch, is_valid):444 class MockDelegate(object):445 def refetch_patch(self, patch):446 return patch447 def expected_failures(self):448 return ExpectedFailures()449 task = CommitQueueTask(MockDelegate(), patch)450 self.assertEquals(task.validate(), is_valid)451 def _mock_patch(self, attachment_dict={}, bug_dict={'bug_status': 'NEW'}, committer="fake"):452 bug = bugzilla.Bug(bug_dict, None)453 patch = bugzilla.Attachment(attachment_dict, bug)454 patch._committer = committer455 return patch456 def test_validate(self):457 self._expect_validate(self._mock_patch(), True)458 self._expect_validate(self._mock_patch({'is_obsolete': True}), False)459 self._expect_validate(self._mock_patch(bug_dict={'bug_status': 'CLOSED'}), False)460 self._expect_validate(self._mock_patch(committer=None), False)...
queues.py
Source:queues.py
...67 self._tool.bugs.add_cc_to_bug(bug_id, self.watchers)68 except Exception, e:69 traceback.print_exc()70 log("Failed to CC watchers.")71 def run_webkit_patch(self, args):72 webkit_patch_args = [self._tool.path()]73 # FIXME: This is a hack, we should have a more general way to pass global options.74 # FIXME: We must always pass global options and their value in one argument75 # because our global option code looks for the first argument which does76 # not begin with "-" and assumes that is the command name.77 webkit_patch_args += ["--status-host=%s" % self._tool.status_server.host]78 if self._tool.status_server.bot_id:79 webkit_patch_args += ["--bot-id=%s" % self._tool.status_server.bot_id]80 if self._options.port:81 webkit_patch_args += ["--port=%s" % self._options.port]82 webkit_patch_args.extend(args)83 # FIXME: There is probably no reason to use run_and_throw_if_fail anymore.84 # run_and_throw_if_fail was invented to support tee'd output85 # (where we write both to a log file and to the console at once),86 # but the queues don't need live-progress, a dump-of-output at the87 # end should be sufficient.88 return self._tool.executive.run_and_throw_if_fail(webkit_patch_args, cwd=self._tool.scm().checkout_root)89 def _log_directory(self):90 return os.path.join("..", "%s-logs" % self.name)91 # QueueEngineDelegate methods92 def queue_log_path(self):93 return os.path.join(self._log_directory(), "%s.log" % self.name)94 def work_item_log_path(self, work_item):95 raise NotImplementedError, "subclasses must implement"96 def begin_work_queue(self):97 log("CAUTION: %s will discard all local changes in \"%s\"" % (self.name, self._tool.scm().checkout_root))98 if self._options.confirm:99 response = self._tool.user.prompt("Are you sure? Type \"yes\" to continue: ")100 if (response != "yes"):101 error("User declined.")102 log("Running WebKit %s." % self.name)103 self._tool.status_server.update_status(self.name, "Starting Queue")104 def stop_work_queue(self, reason):105 self._tool.status_server.update_status(self.name, "Stopping Queue, reason: %s" % reason)106 def should_continue_work_queue(self):107 self._iteration_count += 1108 return not self._options.iterations or self._iteration_count <= self._options.iterations109 def next_work_item(self):110 raise NotImplementedError, "subclasses must implement"111 def should_proceed_with_work_item(self, work_item):112 raise NotImplementedError, "subclasses must implement"113 def process_work_item(self, work_item):114 raise NotImplementedError, "subclasses must implement"115 def handle_unexpected_error(self, work_item, message):116 raise NotImplementedError, "subclasses must implement"117 # Command methods118 def execute(self, options, args, tool, engine=QueueEngine):119 self._options = options # FIXME: This code is wrong. Command.options is a list, this assumes an Options element!120 self._tool = tool # FIXME: This code is wrong too! Command.bind_to_tool handles this!121 return engine(self.name, self, self._tool.wakeup_event).run()122 @classmethod123 def _log_from_script_error_for_upload(cls, script_error, output_limit=None):124 # We have seen request timeouts with app engine due to large125 # log uploads. Trying only the last 512k.126 if not output_limit:127 output_limit = 512 * 1024 # 512k128 output = script_error.message_with_output(output_limit=output_limit)129 # We pre-encode the string to a byte array before passing it130 # to status_server, because ClientForm (part of mechanize)131 # wants a file-like object with pre-encoded data.132 return StringIO(output.encode("utf-8"))133 @classmethod134 def _update_status_for_script_error(cls, tool, state, script_error, is_error=False):135 message = str(script_error)136 if is_error:137 message = "Error: %s" % message138 failure_log = cls._log_from_script_error_for_upload(script_error)139 return tool.status_server.update_status(cls.name, message, state["patch"], failure_log)140class FeederQueue(AbstractQueue):141 name = "feeder-queue"142 _sleep_duration = 30 # seconds143 # AbstractQueue methods144 def begin_work_queue(self):145 AbstractQueue.begin_work_queue(self)146 self.feeders = [147 CommitQueueFeeder(self._tool),148 EWSFeeder(self._tool),149 ]150 def next_work_item(self):151 # This really show inherit from some more basic class that doesn't152 # understand work items, but the base class in the heirarchy currently153 # understands work items.154 return "synthetic-work-item"155 def should_proceed_with_work_item(self, work_item):156 return True157 def process_work_item(self, work_item):158 for feeder in self.feeders:159 feeder.feed()160 time.sleep(self._sleep_duration)161 return True162 def work_item_log_path(self, work_item):163 return None164 def handle_unexpected_error(self, work_item, message):165 log(message)166class AbstractPatchQueue(AbstractQueue):167 def _update_status(self, message, patch=None, results_file=None):168 return self._tool.status_server.update_status(self.name, message, patch, results_file)169 def _next_patch(self):170 patch_id = self._tool.status_server.next_work_item(self.name)171 if not patch_id:172 return None173 patch = self._tool.bugs.fetch_attachment(patch_id)174 if not patch:175 # FIXME: Using a fake patch because release_work_item has the wrong API.176 # We also don't really need to release the lock (although that's fine),177 # mostly we just need to remove this bogus patch from our queue.178 # If for some reason bugzilla is just down, then it will be re-fed later.179 patch = Attachment({'id': patch_id}, None)180 self._release_work_item(patch)181 return None182 return patch183 def _release_work_item(self, patch):184 self._tool.status_server.release_work_item(self.name, patch)185 def _did_pass(self, patch):186 self._update_status(self._pass_status, patch)187 self._release_work_item(patch)188 def _did_fail(self, patch):189 self._update_status(self._fail_status, patch)190 self._release_work_item(patch)191 def _did_retry(self, patch):192 self._update_status(self._retry_status, patch)193 self._release_work_item(patch)194 def _did_error(self, patch, reason):195 message = "%s: %s" % (self._error_status, reason)196 self._update_status(message, patch)197 self._release_work_item(patch)198 # FIXME: This probably belongs at a layer below AbstractPatchQueue, but shared by CommitQueue and the EarlyWarningSystem.199 def _upload_results_archive_for_patch(self, patch, results_archive_zip):200 bot_id = self._tool.status_server.bot_id or "bot"201 description = "Archive of layout-test-results from %s" % bot_id202 # results_archive is a ZipFile object, grab the File object (.fp) to pass to Mechanize for uploading.203 results_archive_file = results_archive_zip.fp204 # Rewind the file object to start (since Mechanize won't do that automatically)205 # See https://bugs.webkit.org/show_bug.cgi?id=54593206 results_archive_file.seek(0)207 # FIXME: This is a small lie to always say run-webkit-tests since Chromium uses new-run-webkit-tests.208 # We could make this code look up the test script name off the port.209 comment_text = "The attached test failures were seen while running run-webkit-tests on the %s.\n" % (self.name)210 # FIXME: We could easily list the test failures from the archive here,211 # currently callers do that separately.212 comment_text += BotInfo(self._tool).summary_text()213 self._tool.bugs.add_attachment_to_bug(patch.bug_id(), results_archive_file, description, filename="layout-test-results.zip", comment_text=comment_text)214 def work_item_log_path(self, patch):215 return os.path.join(self._log_directory(), "%s.log" % patch.bug_id())216class CommitQueue(AbstractPatchQueue, StepSequenceErrorHandler, CommitQueueTaskDelegate):217 name = "commit-queue"218 # AbstractPatchQueue methods219 def begin_work_queue(self):220 AbstractPatchQueue.begin_work_queue(self)221 self.committer_validator = CommitterValidator(self._tool.bugs)222 self._expected_failures = ExpectedFailures()223 self._layout_test_results_reader = LayoutTestResultsReader(self._tool, self._log_directory())224 def next_work_item(self):225 return self._next_patch()226 def should_proceed_with_work_item(self, patch):227 patch_text = "rollout patch" if patch.is_rollout() else "patch"228 self._update_status("Processing %s" % patch_text, patch)229 return True230 def process_work_item(self, patch):231 self._cc_watchers(patch.bug_id())232 task = CommitQueueTask(self, patch)233 try:234 if task.run():235 self._did_pass(patch)236 return True237 self._did_retry(patch)238 except ScriptError, e:239 validator = CommitterValidator(self._tool.bugs)240 validator.reject_patch_from_commit_queue(patch.id(), self._error_message_for_bug(task.failure_status_id, e))241 results_archive = task.results_archive_from_patch_test_run(patch)242 if results_archive:243 self._upload_results_archive_for_patch(patch, results_archive)244 self._did_fail(patch)245 def _error_message_for_bug(self, status_id, script_error):246 if not script_error.output:247 return script_error.message_with_output()248 results_link = self._tool.status_server.results_url_for_status(status_id)249 return "%s\nFull output: %s" % (script_error.message_with_output(), results_link)250 def handle_unexpected_error(self, patch, message):251 self.committer_validator.reject_patch_from_commit_queue(patch.id(), message)252 # CommitQueueTaskDelegate methods253 def run_command(self, command):254 self.run_webkit_patch(command)255 def command_passed(self, message, patch):256 self._update_status(message, patch=patch)257 def command_failed(self, message, script_error, patch):258 failure_log = self._log_from_script_error_for_upload(script_error)259 return self._update_status(message, patch=patch, results_file=failure_log)260 def expected_failures(self):261 return self._expected_failures262 def layout_test_results(self):263 return self._layout_test_results_reader.results()264 def archive_last_layout_test_results(self, patch):265 return self._layout_test_results_reader.archive(patch)266 def build_style(self):267 return "both"268 def refetch_patch(self, patch):269 return self._tool.bugs.fetch_attachment(patch.id())270 def report_flaky_tests(self, patch, flaky_test_results, results_archive=None):271 reporter = FlakyTestReporter(self._tool, self.name)272 reporter.report_flaky_tests(patch, flaky_test_results, results_archive)273 # StepSequenceErrorHandler methods274 def handle_script_error(cls, tool, state, script_error):275 # Hitting this error handler should be pretty rare. It does occur,276 # however, when a patch no longer applies to top-of-tree in the final277 # land step.278 log(script_error.message_with_output())279 @classmethod280 def handle_checkout_needs_update(cls, tool, state, options, error):281 message = "Tests passed, but commit failed (checkout out of date). Updating, then landing without building or re-running tests."282 tool.status_server.update_status(cls.name, message, state["patch"])283 # The only time when we find out that out checkout needs update is284 # when we were ready to actually pull the trigger and land the patch.285 # Rather than spinning in the master process, we retry without286 # building or testing, which is much faster.287 options.build = False288 options.test = False289 options.update = True290 raise TryAgain()291class AbstractReviewQueue(AbstractPatchQueue, StepSequenceErrorHandler):292 """This is the base-class for the EWS queues and the style-queue."""293 def __init__(self, options=None):294 AbstractPatchQueue.__init__(self, options)295 def review_patch(self, patch):296 raise NotImplementedError("subclasses must implement")297 # AbstractPatchQueue methods298 def begin_work_queue(self):299 AbstractPatchQueue.begin_work_queue(self)300 def next_work_item(self):301 return self._next_patch()302 def should_proceed_with_work_item(self, patch):303 raise NotImplementedError("subclasses must implement")304 def process_work_item(self, patch):305 try:306 if not self.review_patch(patch):307 return False308 self._did_pass(patch)309 return True310 except ScriptError, e:311 if e.exit_code != QueueEngine.handled_error_code:312 self._did_fail(patch)313 else:314 # The subprocess handled the error, but won't have released the patch, so we do.315 # FIXME: We need to simplify the rules by which _release_work_item is called.316 self._release_work_item(patch)317 raise e318 def handle_unexpected_error(self, patch, message):319 log(message)320 # StepSequenceErrorHandler methods321 @classmethod322 def handle_script_error(cls, tool, state, script_error):323 log(script_error.message_with_output())324class StyleQueue(AbstractReviewQueue):325 name = "style-queue"326 def __init__(self):327 AbstractReviewQueue.__init__(self)328 def should_proceed_with_work_item(self, patch):329 self._update_status("Checking style", patch)330 return True331 def review_patch(self, patch):332 self.run_webkit_patch(["check-style", "--force-clean", "--non-interactive", "--parent-command=style-queue", patch.id()])333 self.run_webkit_patch(["apply-watchlist-local", patch.bug_id()])334 return True335 @classmethod336 def handle_script_error(cls, tool, state, script_error):337 is_svn_apply = script_error.command_name() == "svn-apply"338 status_id = cls._update_status_for_script_error(tool, state, script_error, is_error=is_svn_apply)339 if is_svn_apply:340 QueueEngine.exit_after_handled_error(script_error)341 message = "Attachment %s did not pass %s:\n\n%s\n\nIf any of these errors are false positives, please file a bug against check-webkit-style." % (state["patch"].id(), cls.name, script_error.message_with_output(output_limit=3*1024))342 tool.bugs.post_comment_to_bug(state["patch"].bug_id(), message, cc=cls.watchers)...
patch_test.py
Source:patch_test.py
...12sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))13from testing_support.patches_data import GIT, RAW14import patch15class PatchTest(unittest.TestCase):16 def _check_patch(self,17 p,18 filename,19 diff,20 source_filename=None,21 is_binary=False,22 is_delete=False,23 is_git_diff=False,24 is_new=False,25 patchlevel=0,26 svn_properties=None,27 nb_hunks=None):28 self.assertEquals(p.filename, filename)29 self.assertEquals(p.source_filename, source_filename)30 self.assertEquals(p.is_binary, is_binary)31 self.assertEquals(p.is_delete, is_delete)32 if hasattr(p, 'is_git_diff'):33 self.assertEquals(p.is_git_diff, is_git_diff)34 self.assertEquals(p.is_new, is_new)35 if hasattr(p, 'patchlevel'):36 self.assertEquals(p.patchlevel, patchlevel)37 if diff:38 if is_binary:39 self.assertEquals(p.get(), diff)40 else:41 self.assertEquals(p.get(True), diff)42 if hasattr(p, 'hunks'):43 self.assertEquals(len(p.hunks), nb_hunks)44 else:45 self.assertEquals(None, nb_hunks)46 if hasattr(p, 'svn_properties'):47 self.assertEquals(p.svn_properties, svn_properties or [])48 def testFilePatchDelete(self):49 p = patch.FilePatchDelete('foo', False)50 self._check_patch(p, 'foo', None, is_delete=True)51 def testFilePatchDeleteBin(self):52 p = patch.FilePatchDelete('foo', True)53 self._check_patch(p, 'foo', None, is_delete=True, is_binary=True)54 def testFilePatchBinary(self):55 p = patch.FilePatchBinary('foo', 'data', [], is_new=False)56 self._check_patch(p, 'foo', 'data', is_binary=True)57 def testFilePatchBinaryNew(self):58 p = patch.FilePatchBinary('foo', 'data', [], is_new=True)59 self._check_patch(p, 'foo', 'data', is_binary=True, is_new=True)60 def testFilePatchDiff(self):61 p = patch.FilePatchDiff('chrome/file.cc', RAW.PATCH, [])62 self._check_patch(p, 'chrome/file.cc', RAW.PATCH, nb_hunks=1)63 def testDifferent(self):64 name = 'master/unittests/data/processes-summary.dat'65 p = patch.FilePatchDiff(name, RAW.DIFFERENT, [])66 self._check_patch(p, name, RAW.DIFFERENT, nb_hunks=1)67 def testFilePatchDiffHeaderMode(self):68 p = patch.FilePatchDiff('git_cl/git-cl', GIT.MODE_EXE, [])69 self._check_patch(70 p, 'git_cl/git-cl', GIT.MODE_EXE, is_git_diff=True, patchlevel=1,71 svn_properties=[('svn:executable', '.')], nb_hunks=0)72 def testFilePatchDiffHeaderModeIndex(self):73 p = patch.FilePatchDiff('git_cl/git-cl', GIT.MODE_EXE_JUNK, [])74 self._check_patch(75 p, 'git_cl/git-cl', GIT.MODE_EXE_JUNK, is_git_diff=True, patchlevel=1,76 svn_properties=[('svn:executable', '.')], nb_hunks=0)77 def testFilePatchDiffHeaderNotExecutable(self):78 p = patch.FilePatchDiff(79 'build/android/ant/create.js', GIT.NEW_NOT_EXECUTABLE, [])80 self._check_patch(81 p, 'build/android/ant/create.js', GIT.NEW_NOT_EXECUTABLE,82 is_git_diff=True, patchlevel=1, is_new=True,83 nb_hunks=1)84 def testFilePatchDiffSvnNew(self):85 # The code path is different for git and svn.86 p = patch.FilePatchDiff('foo', RAW.NEW, [])87 self._check_patch(p, 'foo', RAW.NEW, is_new=True, nb_hunks=1)88 def testFilePatchDiffGitNew(self):89 # The code path is different for git and svn.90 p = patch.FilePatchDiff('foo', GIT.NEW, [])91 self._check_patch(92 p, 'foo', GIT.NEW, is_new=True, is_git_diff=True, patchlevel=1,93 nb_hunks=1)94 def testSvn(self):95 # Should not throw.96 p = patch.FilePatchDiff('chrome/file.cc', RAW.PATCH, [])97 lines = RAW.PATCH.splitlines(True)98 header = ''.join(lines[:4])99 hunks = ''.join(lines[4:])100 self.assertEquals(header, p.diff_header)101 self.assertEquals(hunks, p.diff_hunks)102 self.assertEquals(RAW.PATCH, p.get(True))103 self.assertEquals(RAW.PATCH, p.get(False))104 def testSvnNew(self):105 p = patch.FilePatchDiff('chrome/file.cc', RAW.MINIMAL_NEW, [])106 self.assertEquals(RAW.MINIMAL_NEW, p.diff_header)107 self.assertEquals('', p.diff_hunks)108 self.assertEquals(RAW.MINIMAL_NEW, p.get(True))109 self.assertEquals(RAW.MINIMAL_NEW, p.get(False))110 def testSvnDelete(self):111 p = patch.FilePatchDiff('chrome/file.cc', RAW.MINIMAL_DELETE, [])112 self.assertEquals(RAW.MINIMAL_DELETE, p.diff_header)113 self.assertEquals('', p.diff_hunks)114 self.assertEquals(RAW.MINIMAL_DELETE, p.get(True))115 self.assertEquals(RAW.MINIMAL_DELETE, p.get(False))116 def testSvnRename(self):117 p = patch.FilePatchDiff('file_b', RAW.MINIMAL_RENAME, [])118 self.assertEquals(RAW.MINIMAL_RENAME, p.diff_header)119 self.assertEquals('', p.diff_hunks)120 self.assertEquals(RAW.MINIMAL_RENAME, p.get(True))121 self.assertEquals('--- file_b\n+++ file_b\n', p.get(False))122 def testRelPath(self):123 patches = patch.PatchSet([124 patch.FilePatchDiff('pp', GIT.COPY, []),125 patch.FilePatchDiff(126 'chromeos\\views/webui_menu_widget.h', GIT.RENAME_PARTIAL, []),127 patch.FilePatchDiff('tools/run_local_server.sh', GIT.RENAME, []),128 patch.FilePatchBinary('bar', 'data', [], is_new=False),129 patch.FilePatchDiff('chrome/file.cc', RAW.PATCH, []),130 patch.FilePatchDiff('foo', GIT.NEW, []),131 patch.FilePatchDelete('other/place/foo', True),132 patch.FilePatchDiff(133 'tools\\clang_check/README.chromium', GIT.DELETE, []),134 ])135 expected = [136 'pp',137 'chromeos/views/webui_menu_widget.h',138 'tools/run_local_server.sh',139 'bar',140 'chrome/file.cc',141 'foo',142 'other/place/foo',143 'tools/clang_check/README.chromium',144 ]145 self.assertEquals(expected, patches.filenames)146 # Test patch #4.147 orig_name = patches.patches[4].filename148 orig_source_name = patches.patches[4].source_filename or orig_name149 patches.set_relpath(os.path.join('a', 'bb'))150 # Expect posixpath all the time.151 expected = [posixpath.join('a', 'bb', x) for x in expected]152 self.assertEquals(expected, patches.filenames)153 # Make sure each header is updated accordingly.154 header = []155 new_name = posixpath.join('a', 'bb', orig_name)156 new_source_name = posixpath.join('a', 'bb', orig_source_name)157 for line in RAW.PATCH.splitlines(True):158 if line.startswith('@@'):159 break160 if line[:3] == '---':161 line = line.replace(orig_source_name, new_source_name)162 if line[:3] == '+++':163 line = line.replace(orig_name, new_name)164 header.append(line)165 header = ''.join(header)166 self.assertEquals(header, patches.patches[4].diff_header)167 def testRelPathEmpty(self):168 patches = patch.PatchSet([169 patch.FilePatchDiff('chrome\\file.cc', RAW.PATCH, []),170 patch.FilePatchDelete('other\\place\\foo', True),171 ])172 patches.set_relpath('')173 self.assertEquals(174 ['chrome/file.cc', 'other/place/foo'],175 [f.filename for f in patches])176 self.assertEquals([None, None], [f.source_filename for f in patches])177 def testBackSlash(self):178 mangled_patch = RAW.PATCH.replace('chrome/', 'chrome\\')179 patches = patch.PatchSet([180 patch.FilePatchDiff('chrome\\file.cc', mangled_patch, []),181 patch.FilePatchDelete('other\\place\\foo', True),182 ])183 expected = ['chrome/file.cc', 'other/place/foo']184 self.assertEquals(expected, patches.filenames)185 self.assertEquals(RAW.PATCH, patches.patches[0].get(True))186 self.assertEquals(RAW.PATCH, patches.patches[0].get(False))187 def testTwoHunks(self):188 name = 'chrome/app/generated_resources.grd'189 p = patch.FilePatchDiff(name, RAW.TWO_HUNKS, [])190 self._check_patch(p, name, RAW.TWO_HUNKS, nb_hunks=2)191 def testGitThreeHunks(self):192 p = patch.FilePatchDiff('presubmit_support.py', GIT.FOUR_HUNKS, [])193 self._check_patch(194 p, 'presubmit_support.py', GIT.FOUR_HUNKS, is_git_diff=True,195 patchlevel=1,196 nb_hunks=4)197 def testDelete(self):198 p = patch.FilePatchDiff('tools/clang_check/README.chromium', RAW.DELETE, [])199 self._check_patch(200 p, 'tools/clang_check/README.chromium', RAW.DELETE, is_delete=True,201 nb_hunks=1)202 def testDelete2(self):203 name = 'browser/extensions/extension_sidebar_api.cc'204 p = patch.FilePatchDiff(name, RAW.DELETE2, [])205 self._check_patch(p, name, RAW.DELETE2, is_delete=True, nb_hunks=1)206 def testGitDelete(self):207 p = patch.FilePatchDiff('tools/clang_check/README.chromium', GIT.DELETE, [])208 self._check_patch(209 p, 'tools/clang_check/README.chromium', GIT.DELETE, is_delete=True,210 is_git_diff=True, patchlevel=1, nb_hunks=1)211 def testGitRename(self):212 p = patch.FilePatchDiff('tools/run_local_server.sh', GIT.RENAME, [])213 self._check_patch(214 p,215 'tools/run_local_server.sh',216 GIT.RENAME,217 is_git_diff=True,218 patchlevel=1,219 source_filename='tools/run_local_server.PY',220 is_new=True,221 nb_hunks=0)222 def testGitRenamePartial(self):223 p = patch.FilePatchDiff(224 'chromeos/views/webui_menu_widget.h', GIT.RENAME_PARTIAL, [])225 self._check_patch(226 p,227 'chromeos/views/webui_menu_widget.h',228 GIT.RENAME_PARTIAL,229 source_filename='chromeos/views/DOMui_menu_widget.h',230 is_git_diff=True,231 patchlevel=1,232 is_new=True,233 nb_hunks=1)234 def testGitCopy(self):235 p = patch.FilePatchDiff('pp', GIT.COPY, [])236 self._check_patch(237 p, 'pp', GIT.COPY, is_git_diff=True, patchlevel=1,238 source_filename='PRESUBMIT.py', is_new=True, nb_hunks=0)239 def testOnlyHeader(self):240 p = patch.FilePatchDiff('file_a', RAW.MINIMAL, [])241 self._check_patch(p, 'file_a', RAW.MINIMAL, nb_hunks=0)242 def testSmallest(self):243 p = patch.FilePatchDiff('file_a', RAW.NEW_NOT_NULL, [])244 self._check_patch(p, 'file_a', RAW.NEW_NOT_NULL, is_new=True, nb_hunks=1)245 def testRenameOnlyHeader(self):246 p = patch.FilePatchDiff('file_b', RAW.MINIMAL_RENAME, [])247 self._check_patch(248 p, 'file_b', RAW.MINIMAL_RENAME, source_filename='file_a', is_new=True,249 nb_hunks=0)250 def testUnicodeFilenameGet(self):251 p = patch.FilePatchDiff(u'filé_b', RAW.RENAME_UTF8, [])252 self._check_patch(253 p, u'filé_b', RAW.RENAME_UTF8, source_filename=u'file_à ', is_new=True,254 nb_hunks=1)255 self.assertTrue(isinstance(p.get(False), str))256 p.set_relpath('foo')257 self.assertTrue(isinstance(p.get(False), str))258 self.assertEquals(u'foo/file_à '.encode('utf-8'), p.source_filename_utf8)259 self.assertEquals(u'foo/file_à ', p.source_filename)260 self.assertEquals(u'foo/filé_b'.encode('utf-8'), p.filename_utf8)261 self.assertEquals(u'foo/filé_b', p.filename)262 def testGitCopyPartial(self):263 p = patch.FilePatchDiff('wtf2', GIT.COPY_PARTIAL, [])264 self._check_patch(265 p, 'wtf2', GIT.COPY_PARTIAL, source_filename='wtf', is_git_diff=True,266 patchlevel=1, is_new=True, nb_hunks=1)267 def testGitCopyPartialAsSvn(self):268 p = patch.FilePatchDiff('wtf2', GIT.COPY_PARTIAL, [])269 # TODO(maruel): Improve processing.270 diff = (271 'diff --git a/wtf2 b/wtf22\n'272 'similarity index 98%\n'273 'copy from wtf2\n'274 'copy to wtf22\n'275 'index 79fbaf3..3560689 100755\n'276 '--- a/wtf2\n'277 '+++ b/wtf22\n'278 '@@ -1,4 +1,4 @@\n'279 '-#!/usr/bin/env python\n'280 '+#!/usr/bin/env python1.3\n'281 ' # Copyright (c) 2010 The Chromium Authors. All rights reserved.\n'282 ' # blah blah blah as\n'283 ' # found in the LICENSE file.\n')284 self.assertEquals(diff, p.get(False))285 def testGitNewExe(self):286 p = patch.FilePatchDiff('natsort_test.py', GIT.NEW_EXE, [])287 self._check_patch(288 p,289 'natsort_test.py',290 GIT.NEW_EXE,291 is_new=True,292 is_git_diff=True,293 patchlevel=1,294 svn_properties=[('svn:executable', '.')],295 nb_hunks=1)296 def testGitNewMode(self):297 p = patch.FilePatchDiff('natsort_test.py', GIT.NEW_MODE, [])298 self._check_patch(299 p, 'natsort_test.py', GIT.NEW_MODE, is_new=True, is_git_diff=True,300 patchlevel=1, nb_hunks=1)301 def testPatchsetOrder(self):302 # Deletes must be last.303 # File renames/move/copy must be first.304 patches = [305 patch.FilePatchDiff('chrome/file.cc', RAW.PATCH, []),306 patch.FilePatchDiff(307 'tools\\clang_check/README.chromium', GIT.DELETE, []),308 patch.FilePatchDiff('tools/run_local_server.sh', GIT.RENAME, []),309 patch.FilePatchDiff(310 'chromeos\\views/webui_menu_widget.h', GIT.RENAME_PARTIAL, []),311 patch.FilePatchDiff('pp', GIT.COPY, []),312 patch.FilePatchDiff('foo', GIT.NEW, []),313 patch.FilePatchDelete('other/place/foo', True),314 patch.FilePatchBinary('bar', 'data', [], is_new=False),315 ]316 expected = [317 'pp',318 'chromeos/views/webui_menu_widget.h',319 'tools/run_local_server.sh',320 'bar',321 'chrome/file.cc',322 'foo',323 'other/place/foo',324 'tools/clang_check/README.chromium',325 ]326 patchset = patch.PatchSet(patches)327 self.assertEquals(expected, patchset.filenames)328 def testGitPatch(self):329 p = patch.FilePatchDiff('chrome/file.cc', GIT.PATCH, [])330 self._check_patch(331 p, 'chrome/file.cc', GIT.PATCH, is_git_diff=True, patchlevel=1,332 nb_hunks=1)333 def testGitPatchShortHunkHeader(self):334 p = patch.FilePatchDiff(335 'chrome/browser/api/OWNERS', GIT.PATCH_SHORT_HUNK_HEADER, [])336 self._check_patch(337 p, 'chrome/browser/api/OWNERS', GIT.PATCH_SHORT_HUNK_HEADER,338 is_git_diff=True, patchlevel=1, nb_hunks=1)339class PatchTestFail(unittest.TestCase):340 # All patches that should throw.341 def testFilePatchDelete(self):342 self.assertFalse(hasattr(patch.FilePatchDelete('foo', False), 'get'))343 def testFilePatchDeleteBin(self):344 self.assertFalse(hasattr(patch.FilePatchDelete('foo', True), 'get'))345 def testFilePatchDiffBad(self):346 try:347 patch.FilePatchDiff('foo', 'data', [])348 self.fail()349 except patch.UnsupportedPatchFormat:350 pass...
wrapper.js
Source:wrapper.js
1var DB = require('./base');2var debug = false;3exports.getAllPatches = ((limit) => {4 return new Promise((resolve, reject) => {5 if(!limit){6 limit = 2147483647;7 }8 DB.query(`9 SELECT *10 FROM patch11 ORDER BY date DESC12 LIMIT ?13 `, [limit], ((data, error) => {14 if(!error){15 if(debug) console.log('[DEBUG][getAllPatches] result:', data);16 resolve(data);17 }else{18 if(debug) console.log('[DEBUG][getAllPatches] error:', error);19 reject();20 }21 }));22 });23});24exports.getCurrentPatch = (() => {25 return new Promise((resolve, reject) => {26 DB.query(`27 SELECT *28 FROM patch29 ORDER BY date DESC30 LIMIT 131 `, null, ((data, error) => {32 if(!error){33 if(debug) console.log('[DEBUG][getCurrentPatch] result:', data);34 resolve(data);35 }else{36 if(debug) console.log('[DEBUG][getCurrentPatch] error:', error);37 reject();38 }39 }));40 });41});42exports.getCurrentPatchForDate = ((date) => {43 return new Promise((resolve, reject) => {44 DB.query(`45 (46 SELECT *47 FROM patch48 WHERE date <= ?49 ORDER BY date DESC50 LIMIT 151 ) UNION (52 SELECT *53 FROM patch54 ORDER BY date ASC55 LIMIT 156 )57 ORDER BY date DESC58 LIMIT 159 `, [date], ((data, error) => {60 if(!error){61 if(debug) console.log('[DEBUG][getCurrentPatchForDate] result:', data);62 resolve(data);63 }else{64 if(debug) console.log('[DEBUG][getCurrentPatchForDate] error:', error);65 reject();66 }67 }));68 });69});70exports.getAllChangesForChampionId = ((championId, limit) => {71 return new Promise((resolve, reject) => {72 if(!limit){73 limit = 2147483647;74 }75 DB.query(`76 SELECT *77 FROM patch_champion_changes78 WHERE championId = ?79 ORDER BY patchId DESC80 LIMIT ?81 `, [championId, limit], ((data, error) => {82 if(!error){83 if(debug) console.log('[DEBUG][getAllChangesForChampionId] result:', data);84 resolve(data);85 }else{86 if(debug) console.log('[DEBUG][getAllChangesForChampionId] error:', error);87 reject();88 }89 }));90 });91});92exports.getAllChangesForChampionIdAfterDate = ((championId, date) => {93 return new Promise((resolve, reject) => {94 DB.query(`95 SELECT *96 FROM patch_champion_changes97 INNER JOIN patch ON (patch.id = patch_champion_changes.patchId)98 WHERE championId = ?99 AND date > ?100 ORDER BY patchId DESC101 `, [championId, date], ((data, error) => {102 if(!error){103 if(debug) console.log('[DEBUG][getAllChangesForChampionIdAfterDate] result:', data);104 resolve(data);105 }else{106 if(debug) console.log('[DEBUG][getAllChangesForChampionIdAfterDate] error:', error);107 reject();108 }109 }));110 });111});112exports.getRelevantItemsForChampionId = ((championId) => {113 return new Promise((resolve, reject) => {114 DB.query(`115 SELECT *116 FROM champion_items117 WHERE championId = ?118 ORDER BY championId DESC119 `, [championId], ((data, error) => {120 if(!error){121 if(debug) console.log('[DEBUG][getRelevantItemsForChampionId] result:', data);122 resolve(data);123 }else{124 if(debug) console.log('[DEBUG][getRelevantItemsForChampionId] error:', error);125 reject();126 }127 }));128 });129});130exports.getRelevantRunesForChampionId = ((championId) => {131 return new Promise((resolve, reject) => {132 DB.query(`133 SELECT *134 FROM champion_runes135 WHERE championId = ?136 ORDER BY runeId DESC137 `, [championId], ((data, error) => {138 if(!error){139 if(debug) console.log('[DEBUG][getRelevantRunesForChampionId] result:', data);140 resolve(data);141 }else{142 if(debug) console.log('[DEBUG][getRelevantRunesForChampionId] error:', error);143 reject();144 }145 }));146 });147});148exports.getItemChangesForPatchIdAndItemId = ((patchId, itemId) => {149 return new Promise((resolve, reject) => {150 DB.query(`151 SELECT *152 FROM patch_item_changes153 WHERE patchId = ?154 AND itemId = ?155 ORDER BY patchId DESC156 `, [patchId, itemId], ((data, error) => {157 if(!error){158 if(debug) console.log('[DEBUG][getItemChangesForPatchIdAndItemId] result:', data);159 resolve(data);160 }else{161 if(debug) console.log('[DEBUG][getItemChangesForPatchIdAndItemId] error:', error);162 reject();163 }164 }));165 });166});167exports.getRuneChangesForPatchIdAndRuneId = ((patchId, runeId) => {168 return new Promise((resolve, reject) => {169 DB.query(`170 SELECT *171 FROM patch_rune_changes172 WHERE patchId = ?173 AND runeId = ?174 ORDER BY patchId DESC175 `, [patchId, runeId], ((data, error) => {176 if(!error){177 if(debug) console.log('[DEBUG][getRuneChangesForPatchIdAndRuneId] result:', data);178 resolve(data);179 }else{180 if(debug) console.log('[DEBUG][getRuneChangesForPatchIdAndRuneId] error:', error);181 reject();182 }183 }));184 });185});186exports.getAllItemChangesForPatchIdAndChampionId = ((patchId, championId) => {187 return new Promise((resolve, reject) => {188 DB.query(`189 SELECT *190 FROM patch_item_changes191 RIGHT JOIN champion_items ON (champion_items.itemId = patch_item_changes.itemId)192 WHERE patch_item_changes.patchId = ?193 AND champion_items.championId = ?194 ORDER BY champion_items.itemId ASC195 `, [patchId, championId], ((data, error) => {196 if(!error){197 if(debug) console.log('[DEBUG][getAllItemChangesForPatchIdAndChampionId] result:', data);198 resolve(data);199 }else{200 if(debug) console.log('[DEBUG][getAllItemChangesForPatchIdAndChampionId] error:', error);201 reject();202 }203 }));204 });205});206exports.getAllRuneChangesForPatchIdAndChampionId = ((patchId, championId) => {207 return new Promise((resolve, reject) => {208 DB.query(`209 SELECT *210 FROM patch_rune_changes211 RIGHT JOIN champion_runes ON (champion_runes.runeId = patch_rune_changes.runeId)212 WHERE patch_rune_changes.patchId = ?213 AND champion_runes.championId = ?214 ORDER BY champion_runes.runeId ASC215 `, [patchId, championId], ((data, error) => {216 if(!error){217 if(debug) console.log('[DEBUG][getAllRuneChangesForPatchIdAndChampionId] result:', data);218 resolve(data);219 }else{220 if(debug) console.log('[DEBUG][getAllRuneChangesForPatchIdAndChampionId] error:', error);221 reject();222 }223 }));224 });225});226exports.getAllPatchesAfterPatchId = ((patchId) => {227 return new Promise((resolve, reject) => {228 DB.query(`229 SELECT *230 FROM patch231 WHERE date >= (232 SELECT date233 FROM patch234 WHERE id = ?235 )236 ORDER BY date DESC237 `, [patchId], ((data, error) => {238 if(!error){239 if(debug) console.log('[DEBUG][getAllPatchesAfterPatchId] result:', data);240 resolve(data);241 }else{242 if(debug) console.log('[DEBUG][getAllPatchesAfterPatchId] error:', error);243 reject();244 }245 }));246 });247});248exports.getAllItemChangesForChampionIdAfterPatchId = ((championId, patchId) => {249 return new Promise(async (resolve, reject) => {250 let result = {};251 let patches = await exports.getAllPatchesAfterPatchId(patchId);252 if(!patches){253 reject();254 return;255 }256 let i = 0;257 patches.forEach(async (patch) => {258 let changes = await exports.getAllItemChangesForPatchIdAndChampionId(patch.id, championId);259 result[patch.id] = changes;260 if(++i == patches.length){261 resolve(result);262 }263 });264 });265});266exports.getAllRuneChangesForChampionIdAfterPatchId = ((championId, patchId) => {267 return new Promise(async (resolve, reject) => {268 let result = {};269 let patches = await exports.getAllPatchesAfterPatchId(patchId);270 if(!patches){271 reject();272 return;273 }274 let i = 0;275 patches.forEach(async (patch) => {276 let changes = await exports.getAllRuneChangesForPatchIdAndChampionId(patch.id, championId);277 result[patch.id] = changes;278 if(++i == patches.length){279 resolve(result);280 }281 });282 });283});284// testing285if(debug){286 exports.getCurrentPatch().then((response) => {287 console.log(response);288 });289// exports.getAllPatches().then((response) => {290// console.log(response);291// });292// var x = exports.getAllItemChangesForChampionIdAfterPatchId(104, '8.1');293// console.log('x', x);294// exports.getAllItemChangesForChampionIdAfterPatchId(15, '8.13').then((response) => {295// console.log('xxx', response);296// });297// exports.getCurrentPatchForDate(new Date('2018-11-08T23:50:00.600Z')).then((response) => {298// console.log(response);299// });300// exports.getAllChangesForChampionIdAfterDate(142, new Date('2018-01-01')).then((response) => {301// console.log(response);302// });303// exports.getAllItemChangesForPatchIdAndChampionId('8.22', 1).then((response) => {304// console.log(response);305// });...
test_patcher.py
Source:test_patcher.py
...44 def test_create_pxe(self):45 node = ironic_utils.get_test_node(driver='pxe_fake')46 patcher_obj = patcher.create(node)47 self.assertIsInstance(patcher_obj, patcher.PXEDriverFields)48 def test_generic_get_deploy_patch(self):49 node = ironic_utils.get_test_node(driver='fake')50 patch = patcher.create(node).get_deploy_patch(51 self.instance, self.image_meta, self.flavor)52 self.assertEqual(sorted(self._expected_deploy_patch), sorted(patch))53 def test_generic_get_deploy_patch_ephemeral(self):54 CONF.set_override('default_ephemeral_format', 'testfmt')55 node = ironic_utils.get_test_node(driver='fake')56 instance = fake_instance.fake_instance_obj(self.ctx,57 ephemeral_gb=10)58 patch = patcher.create(node).get_deploy_patch(59 instance, self.image_meta, self.flavor)60 expected = [{'path': '/instance_info/ephemeral_gb',61 'value': str(instance.ephemeral_gb),62 'op': 'add'},63 {'path': '/instance_info/ephemeral_format',64 'value': 'testfmt',65 'op': 'add'}]66 expected += self._expected_deploy_patch67 self.assertEqual(sorted(expected), sorted(patch))68 def test_generic_get_deploy_patch_preserve_ephemeral(self):69 node = ironic_utils.get_test_node(driver='fake')70 for preserve in [True, False]:71 patch = patcher.create(node).get_deploy_patch(72 self.instance, self.image_meta, self.flavor,73 preserve_ephemeral=preserve)74 expected = [{'path': '/instance_info/preserve_ephemeral',75 'value': str(preserve), 'op': 'add', }]76 expected += self._expected_deploy_patch77 self.assertEqual(sorted(expected), sorted(patch))78 def test_generic_get_cleanup_patch(self):79 node = ironic_utils.get_test_node(driver='fake')80 patch = patcher.create(node).get_cleanup_patch(self.instance, None,81 self.flavor)82 self.assertEqual(self._expected_cleanup_patch, patch)83 def test_pxe_get_deploy_patch(self):84 node = ironic_utils.get_test_node(driver='pxe_fake')85 extra_specs = self.flavor['extra_specs']86 expected = [{'path': '/driver_info/pxe_deploy_kernel',87 'value': extra_specs['baremetal:deploy_kernel_id'],88 'op': 'add'},89 {'path': '/driver_info/pxe_deploy_ramdisk',90 'value': extra_specs['baremetal:deploy_ramdisk_id'],91 'op': 'add'}]92 expected += self._expected_deploy_patch93 patch = patcher.create(node).get_deploy_patch(94 self.instance, self.image_meta, self.flavor)95 self.assertEqual(sorted(expected), sorted(patch))96 def test_pxe_get_deploy_patch_no_flavor_kernel_ramdisk_ids(self):97 flavor = ironic_utils.get_test_flavor(extra_specs={})98 node = ironic_utils.get_test_node(driver='pxe_fake')99 patch = patcher.create(node).get_deploy_patch(100 self.instance, self.image_meta, flavor)101 # If there's no extra_specs patch should be exactly like a102 # generic patch103 self.assertEqual(sorted(self._expected_deploy_patch), sorted(patch))104 def test_pxe_get_cleanup_patch(self):105 driver_info = {'pxe_deploy_kernel': 'fake-kernel-id',106 'pxe_deploy_ramdisk': 'fake-ramdisk-id'}107 node = ironic_utils.get_test_node(driver='pxe_fake',108 driver_info=driver_info)109 patch = patcher.create(node).get_cleanup_patch(self.instance, None,110 self.flavor)111 expected = [{'path': '/driver_info/pxe_deploy_kernel',112 'op': 'remove'},113 {'path': '/driver_info/pxe_deploy_ramdisk',114 'op': 'remove'}]115 self.assertEqual(sorted(expected), sorted(patch))116 def test_pxe_get_cleanup_patch_no_flavor_kernel_ramdisk_ids(self):117 self.flavor = ironic_utils.get_test_flavor(extra_specs={})118 node = ironic_utils.get_test_node(driver='pxe_fake')119 patch = patcher.create(node).get_cleanup_patch(self.instance, None,120 self.flavor)121 # If there's no extra_specs patch should be exactly like a122 # generic patch...
Using AI Code Generation
1const { chromium } = require("playwright");2(async () => {3 const browser = await chromium.launch({ headless: false });4 const context = await browser.newContext();5 const page = await context.newPage();6 const title = await page.title();7 console.log(title);8 await page.patch({9 });10 await page.screenshot({ path: "example.png" });11 await browser.close();12})();
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!