Best Python code snippet using localstack_python
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)...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
