|  | @@ -1,354 +0,0 @@
 | 
	
		
			
				|  |  | -from __future__ import absolute_import, unicode_literals
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -import errno
 | 
	
		
			
				|  |  | -import select
 | 
	
		
			
				|  |  | -import sys
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -from time import time
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -from celery.worker import autoreload
 | 
	
		
			
				|  |  | -from celery.worker.autoreload import (
 | 
	
		
			
				|  |  | -    WorkerComponent,
 | 
	
		
			
				|  |  | -    file_hash,
 | 
	
		
			
				|  |  | -    BaseMonitor,
 | 
	
		
			
				|  |  | -    StatMonitor,
 | 
	
		
			
				|  |  | -    KQueueMonitor,
 | 
	
		
			
				|  |  | -    InotifyMonitor,
 | 
	
		
			
				|  |  | -    default_implementation,
 | 
	
		
			
				|  |  | -    Autoreloader,
 | 
	
		
			
				|  |  | -)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -from celery.tests.case import AppCase, Case, Mock, mock, patch
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -class test_WorkerComponent(AppCase):
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def test_create_threaded(self):
 | 
	
		
			
				|  |  | -        w = Mock()
 | 
	
		
			
				|  |  | -        w.use_eventloop = False
 | 
	
		
			
				|  |  | -        x = WorkerComponent(w)
 | 
	
		
			
				|  |  | -        x.instantiate = Mock()
 | 
	
		
			
				|  |  | -        r = x.create(w)
 | 
	
		
			
				|  |  | -        x.instantiate.assert_called_with(w.autoreloader_cls, w)
 | 
	
		
			
				|  |  | -        self.assertIs(r, w.autoreloader)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    @patch('select.kevent', create=True)
 | 
	
		
			
				|  |  | -    @patch('select.kqueue', create=True)
 | 
	
		
			
				|  |  | -    @patch('kombu.utils.eventio.kqueue')
 | 
	
		
			
				|  |  | -    def test_create_ev(self, kq, kqueue, kevent):
 | 
	
		
			
				|  |  | -        w = Mock()
 | 
	
		
			
				|  |  | -        w.use_eventloop = True
 | 
	
		
			
				|  |  | -        x = WorkerComponent(w)
 | 
	
		
			
				|  |  | -        x.instantiate = Mock()
 | 
	
		
			
				|  |  | -        r = x.create(w)
 | 
	
		
			
				|  |  | -        x.instantiate.assert_called_with(w.autoreloader_cls, w)
 | 
	
		
			
				|  |  | -        x.register_with_event_loop(w, w.hub)
 | 
	
		
			
				|  |  | -        self.assertIsNone(r)
 | 
	
		
			
				|  |  | -        w.hub.on_close.add.assert_called_with(
 | 
	
		
			
				|  |  | -            w.autoreloader.on_event_loop_close,
 | 
	
		
			
				|  |  | -        )
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -class test_file_hash(Case):
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def test_hash(self):
 | 
	
		
			
				|  |  | -        with mock.open() as a:
 | 
	
		
			
				|  |  | -            a.write('the quick brown fox\n')
 | 
	
		
			
				|  |  | -            a.seek(0)
 | 
	
		
			
				|  |  | -            A = file_hash('foo')
 | 
	
		
			
				|  |  | -        with mock.open() as b:
 | 
	
		
			
				|  |  | -            b.write('the quick brown bar\n')
 | 
	
		
			
				|  |  | -            b.seek(0)
 | 
	
		
			
				|  |  | -            B = file_hash('bar')
 | 
	
		
			
				|  |  | -        self.assertNotEqual(A, B)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -class test_BaseMonitor(Case):
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def test_start_stop_on_change(self):
 | 
	
		
			
				|  |  | -        x = BaseMonitor(['a', 'b'])
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        with self.assertRaises(NotImplementedError):
 | 
	
		
			
				|  |  | -            x.start()
 | 
	
		
			
				|  |  | -        x.stop()
 | 
	
		
			
				|  |  | -        x.on_change([])
 | 
	
		
			
				|  |  | -        x._on_change = Mock()
 | 
	
		
			
				|  |  | -        x.on_change('foo')
 | 
	
		
			
				|  |  | -        x._on_change.assert_called_with('foo')
 | 
	
		
			
				|  |  | -        x.on_event_loop_close(Mock())
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -class test_StatMonitor(Case):
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    @patch('os.stat')
 | 
	
		
			
				|  |  | -    def test_start(self, stat):
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        class st(object):
 | 
	
		
			
				|  |  | -            st_mtime = time()
 | 
	
		
			
				|  |  | -        stat.return_value = st()
 | 
	
		
			
				|  |  | -        x = StatMonitor(['a', 'b'])
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        def on_is_set():
 | 
	
		
			
				|  |  | -            if x.shutdown_event.is_set.call_count > 3:
 | 
	
		
			
				|  |  | -                return True
 | 
	
		
			
				|  |  | -            return False
 | 
	
		
			
				|  |  | -        x.shutdown_event = Mock()
 | 
	
		
			
				|  |  | -        x.shutdown_event.is_set.side_effect = on_is_set
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        x.start()
 | 
	
		
			
				|  |  | -        x.shutdown_event = Mock()
 | 
	
		
			
				|  |  | -        stat.side_effect = OSError()
 | 
	
		
			
				|  |  | -        x.start()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def test_register_with_event_loop(self):
 | 
	
		
			
				|  |  | -        hub = Mock(name='hub')
 | 
	
		
			
				|  |  | -        x = StatMonitor(['a'])
 | 
	
		
			
				|  |  | -        x.register_with_event_loop(hub)
 | 
	
		
			
				|  |  | -        hub.call_repeatedly.assert_called_with(2.0, x.find_changes)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    @patch('os.stat')
 | 
	
		
			
				|  |  | -    def test_mtime_stat_raises(self, stat):
 | 
	
		
			
				|  |  | -        stat.side_effect = ValueError()
 | 
	
		
			
				|  |  | -        x = StatMonitor(['a', 'b'])
 | 
	
		
			
				|  |  | -        x._mtime('a')
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -class test_KQueueMonitor(Case):
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    @patch('select.kqueue', create=True)
 | 
	
		
			
				|  |  | -    @patch('os.close')
 | 
	
		
			
				|  |  | -    def test_stop(self, close, kqueue):
 | 
	
		
			
				|  |  | -        x = KQueueMonitor(['a', 'b'])
 | 
	
		
			
				|  |  | -        x.poller = Mock()
 | 
	
		
			
				|  |  | -        x.filemap['a'] = 10
 | 
	
		
			
				|  |  | -        x.stop()
 | 
	
		
			
				|  |  | -        x.poller.close.assert_called_with()
 | 
	
		
			
				|  |  | -        close.assert_called_with(10)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        close.side_effect = OSError()
 | 
	
		
			
				|  |  | -        close.side_effect.errno = errno.EBADF
 | 
	
		
			
				|  |  | -        x.stop()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    @patch('kombu.utils.eventio.kqueue', create=True)
 | 
	
		
			
				|  |  | -    def test_register_with_event_loop(self, kqueue):
 | 
	
		
			
				|  |  | -        x = KQueueMonitor(['a', 'b'])
 | 
	
		
			
				|  |  | -        hub = Mock(name='hub')
 | 
	
		
			
				|  |  | -        x.add_events = Mock(name='add_events()')
 | 
	
		
			
				|  |  | -        x.register_with_event_loop(hub)
 | 
	
		
			
				|  |  | -        x.add_events.assert_called_with(x._kq)
 | 
	
		
			
				|  |  | -        self.assertEqual(
 | 
	
		
			
				|  |  | -            x._kq.on_file_change,
 | 
	
		
			
				|  |  | -            x.handle_event,
 | 
	
		
			
				|  |  | -        )
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def test_register_with_event_loop_no_kqueue(self):
 | 
	
		
			
				|  |  | -        from kombu.utils import eventio
 | 
	
		
			
				|  |  | -        prev, eventio.kqueue = eventio.kqueue, None
 | 
	
		
			
				|  |  | -        try:
 | 
	
		
			
				|  |  | -            x = KQueueMonitor(['a'])
 | 
	
		
			
				|  |  | -            x.register_with_event_loop(Mock())
 | 
	
		
			
				|  |  | -        finally:
 | 
	
		
			
				|  |  | -            eventio.kqueue = prev
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def test_on_event_loop_close(self):
 | 
	
		
			
				|  |  | -        x = KQueueMonitor(['a', 'b'])
 | 
	
		
			
				|  |  | -        x.close = Mock()
 | 
	
		
			
				|  |  | -        x._kq = Mock(name='_kq')
 | 
	
		
			
				|  |  | -        x.on_event_loop_close(Mock(name='hub'))
 | 
	
		
			
				|  |  | -        x.close.assert_called_with(x._kq)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def test_handle_event(self):
 | 
	
		
			
				|  |  | -        x = KQueueMonitor(['a', 'b'])
 | 
	
		
			
				|  |  | -        x.on_change = Mock()
 | 
	
		
			
				|  |  | -        eA = Mock()
 | 
	
		
			
				|  |  | -        eA.ident = 'a'
 | 
	
		
			
				|  |  | -        eB = Mock()
 | 
	
		
			
				|  |  | -        eB.ident = 'b'
 | 
	
		
			
				|  |  | -        x.fdmap = {'a': 'A', 'b': 'B'}
 | 
	
		
			
				|  |  | -        x.handle_event([eA, eB])
 | 
	
		
			
				|  |  | -        x.on_change.assert_called_with(['A', 'B'])
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    @patch('kombu.utils.eventio.kqueue', create=True)
 | 
	
		
			
				|  |  | -    @patch('kombu.utils.eventio.kevent', create=True)
 | 
	
		
			
				|  |  | -    @patch('os.open')
 | 
	
		
			
				|  |  | -    @patch('select.kqueue', create=True)
 | 
	
		
			
				|  |  | -    def test_start(self, _kq, osopen, kevent, kqueue):
 | 
	
		
			
				|  |  | -        from kombu.utils import eventio
 | 
	
		
			
				|  |  | -        prev_poll, eventio.poll = eventio.poll, kqueue
 | 
	
		
			
				|  |  | -        prev = {}
 | 
	
		
			
				|  |  | -        flags = ['KQ_FILTER_VNODE', 'KQ_EV_ADD', 'KQ_EV_ENABLE',
 | 
	
		
			
				|  |  | -                 'KQ_EV_CLEAR', 'KQ_NOTE_WRITE', 'KQ_NOTE_EXTEND']
 | 
	
		
			
				|  |  | -        for i, flag in enumerate(flags):
 | 
	
		
			
				|  |  | -            prev[flag] = getattr(eventio, flag, None)
 | 
	
		
			
				|  |  | -            if not prev[flag]:
 | 
	
		
			
				|  |  | -                setattr(eventio, flag, i)
 | 
	
		
			
				|  |  | -        try:
 | 
	
		
			
				|  |  | -            kq = kqueue.return_value = Mock()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            class ev(object):
 | 
	
		
			
				|  |  | -                ident = 10
 | 
	
		
			
				|  |  | -                filter = eventio.KQ_FILTER_VNODE
 | 
	
		
			
				|  |  | -            kq.control.return_value = [ev()]
 | 
	
		
			
				|  |  | -            x = KQueueMonitor(['a'])
 | 
	
		
			
				|  |  | -            osopen.return_value = 10
 | 
	
		
			
				|  |  | -            calls = [0]
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            def on_is_set():
 | 
	
		
			
				|  |  | -                calls[0] += 1
 | 
	
		
			
				|  |  | -                if calls[0] > 2:
 | 
	
		
			
				|  |  | -                    return True
 | 
	
		
			
				|  |  | -                return False
 | 
	
		
			
				|  |  | -            x.shutdown_event = Mock()
 | 
	
		
			
				|  |  | -            x.shutdown_event.is_set.side_effect = on_is_set
 | 
	
		
			
				|  |  | -            x.start()
 | 
	
		
			
				|  |  | -        finally:
 | 
	
		
			
				|  |  | -            for flag in flags:
 | 
	
		
			
				|  |  | -                if prev[flag]:
 | 
	
		
			
				|  |  | -                    setattr(eventio, flag, prev[flag])
 | 
	
		
			
				|  |  | -                else:
 | 
	
		
			
				|  |  | -                    delattr(eventio, flag)
 | 
	
		
			
				|  |  | -            eventio.poll = prev_poll
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -class test_InotifyMonitor(Case):
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    @patch('celery.worker.autoreload.pyinotify')
 | 
	
		
			
				|  |  | -    def test_start(self, inotify):
 | 
	
		
			
				|  |  | -        x = InotifyMonitor(['a'])
 | 
	
		
			
				|  |  | -        inotify.IN_MODIFY = 1
 | 
	
		
			
				|  |  | -        inotify.IN_ATTRIB = 2
 | 
	
		
			
				|  |  | -        x.start()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        inotify.WatchManager.side_effect = ValueError()
 | 
	
		
			
				|  |  | -        with self.assertRaises(ValueError):
 | 
	
		
			
				|  |  | -            x.start()
 | 
	
		
			
				|  |  | -        x.stop()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        x._on_change = None
 | 
	
		
			
				|  |  | -        x.process_(Mock())
 | 
	
		
			
				|  |  | -        x._on_change = Mock()
 | 
	
		
			
				|  |  | -        x.process_(Mock())
 | 
	
		
			
				|  |  | -        x._on_change.assert_called()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        x.create_notifier = Mock()
 | 
	
		
			
				|  |  | -        x._wm = Mock()
 | 
	
		
			
				|  |  | -        hub = Mock()
 | 
	
		
			
				|  |  | -        x.register_with_event_loop(hub)
 | 
	
		
			
				|  |  | -        x.create_notifier.assert_called_with()
 | 
	
		
			
				|  |  | -        hub.add_reader.assert_called_with(x._wm.get_fd(), x.on_readable)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        x.on_event_loop_close(hub)
 | 
	
		
			
				|  |  | -        x._notifier = Mock()
 | 
	
		
			
				|  |  | -        x.on_readable()
 | 
	
		
			
				|  |  | -        x._notifier.read_events.assert_called_with()
 | 
	
		
			
				|  |  | -        x._notifier.process_events.assert_called_with()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -class test_default_implementation(Case):
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    @patch('select.kqueue', create=True)
 | 
	
		
			
				|  |  | -    @patch('kombu.utils.eventio.kqueue', create=True)
 | 
	
		
			
				|  |  | -    def test_kqueue(self, kq, kqueue):
 | 
	
		
			
				|  |  | -        self.assertEqual(default_implementation(), 'kqueue')
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    @patch('celery.worker.autoreload.pyinotify')
 | 
	
		
			
				|  |  | -    def test_inotify(self, pyinotify):
 | 
	
		
			
				|  |  | -        kq = getattr(select, 'kqueue', None)
 | 
	
		
			
				|  |  | -        try:
 | 
	
		
			
				|  |  | -            delattr(select, 'kqueue')
 | 
	
		
			
				|  |  | -        except AttributeError:
 | 
	
		
			
				|  |  | -            pass
 | 
	
		
			
				|  |  | -        platform, sys.platform = sys.platform, 'linux'
 | 
	
		
			
				|  |  | -        try:
 | 
	
		
			
				|  |  | -            self.assertEqual(default_implementation(), 'inotify')
 | 
	
		
			
				|  |  | -            ino, autoreload.pyinotify = autoreload.pyinotify, None
 | 
	
		
			
				|  |  | -            try:
 | 
	
		
			
				|  |  | -                self.assertEqual(default_implementation(), 'stat')
 | 
	
		
			
				|  |  | -            finally:
 | 
	
		
			
				|  |  | -                autoreload.pyinotify = ino
 | 
	
		
			
				|  |  | -        finally:
 | 
	
		
			
				|  |  | -            if kq:
 | 
	
		
			
				|  |  | -                select.kqueue = kq
 | 
	
		
			
				|  |  | -            sys.platform = platform
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -class test_Autoreloader(AppCase):
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def test_register_with_event_loop(self):
 | 
	
		
			
				|  |  | -        x = Autoreloader(Mock(), modules=[__name__])
 | 
	
		
			
				|  |  | -        hub = Mock()
 | 
	
		
			
				|  |  | -        x._monitor = None
 | 
	
		
			
				|  |  | -        x.on_init = Mock()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        def se(*args, **kwargs):
 | 
	
		
			
				|  |  | -            x._monitor = Mock()
 | 
	
		
			
				|  |  | -        x.on_init.side_effect = se
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        x.register_with_event_loop(hub)
 | 
	
		
			
				|  |  | -        x.on_init.assert_called_with()
 | 
	
		
			
				|  |  | -        x._monitor.register_with_event_loop.assert_called_with(hub)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        x._monitor.register_with_event_loop.reset_mock()
 | 
	
		
			
				|  |  | -        x.register_with_event_loop(hub)
 | 
	
		
			
				|  |  | -        x._monitor.register_with_event_loop.assert_called_with(hub)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def test_on_event_loop_close(self):
 | 
	
		
			
				|  |  | -        x = Autoreloader(Mock(), modules=[__name__])
 | 
	
		
			
				|  |  | -        hub = Mock()
 | 
	
		
			
				|  |  | -        x._monitor = Mock()
 | 
	
		
			
				|  |  | -        x.on_event_loop_close(hub)
 | 
	
		
			
				|  |  | -        x._monitor.on_event_loop_close.assert_called_with(hub)
 | 
	
		
			
				|  |  | -        x._monitor = None
 | 
	
		
			
				|  |  | -        x.on_event_loop_close(hub)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    @patch('celery.worker.autoreload.file_hash')
 | 
	
		
			
				|  |  | -    def test_start(self, fhash):
 | 
	
		
			
				|  |  | -        x = Autoreloader(Mock(), modules=[__name__])
 | 
	
		
			
				|  |  | -        x.Monitor = Mock()
 | 
	
		
			
				|  |  | -        mon = x.Monitor.return_value = Mock()
 | 
	
		
			
				|  |  | -        mon.start.side_effect = OSError()
 | 
	
		
			
				|  |  | -        mon.start.side_effect.errno = errno.EINTR
 | 
	
		
			
				|  |  | -        x.body()
 | 
	
		
			
				|  |  | -        mon.start.side_effect.errno = errno.ENOENT
 | 
	
		
			
				|  |  | -        with self.assertRaises(OSError):
 | 
	
		
			
				|  |  | -            x.body()
 | 
	
		
			
				|  |  | -        mon.start.side_effect = None
 | 
	
		
			
				|  |  | -        x.body()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    @patch('celery.worker.autoreload.file_hash')
 | 
	
		
			
				|  |  | -    @patch('os.path.exists')
 | 
	
		
			
				|  |  | -    def test_maybe_modified(self, exists, fhash):
 | 
	
		
			
				|  |  | -        exists.return_value = True
 | 
	
		
			
				|  |  | -        fhash.return_value = 'abcd'
 | 
	
		
			
				|  |  | -        x = Autoreloader(Mock(), modules=[__name__])
 | 
	
		
			
				|  |  | -        x._hashes = {}
 | 
	
		
			
				|  |  | -        x._hashes[__name__] = 'dcba'
 | 
	
		
			
				|  |  | -        self.assertTrue(x._maybe_modified(__name__))
 | 
	
		
			
				|  |  | -        x._hashes[__name__] = 'abcd'
 | 
	
		
			
				|  |  | -        self.assertFalse(x._maybe_modified(__name__))
 | 
	
		
			
				|  |  | -        exists.return_value = False
 | 
	
		
			
				|  |  | -        self.assertFalse(x._maybe_modified(__name__))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def test_on_change(self):
 | 
	
		
			
				|  |  | -        x = Autoreloader(Mock(), modules=[__name__])
 | 
	
		
			
				|  |  | -        mm = x._maybe_modified = Mock(0)
 | 
	
		
			
				|  |  | -        mm.return_value = True
 | 
	
		
			
				|  |  | -        x._reload = Mock()
 | 
	
		
			
				|  |  | -        x.file_to_module[__name__] = __name__
 | 
	
		
			
				|  |  | -        x.on_change([__name__])
 | 
	
		
			
				|  |  | -        x._reload.assert_called()
 | 
	
		
			
				|  |  | -        mm.return_value = False
 | 
	
		
			
				|  |  | -        x.on_change([__name__])
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def test_reload(self):
 | 
	
		
			
				|  |  | -        x = Autoreloader(Mock(), modules=[__name__])
 | 
	
		
			
				|  |  | -        x._reload([__name__])
 | 
	
		
			
				|  |  | -        x.controller.reload.assert_called_with([__name__], reload=True)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    def test_stop(self):
 | 
	
		
			
				|  |  | -        x = Autoreloader(Mock(), modules=[__name__])
 | 
	
		
			
				|  |  | -        x._monitor = None
 | 
	
		
			
				|  |  | -        x.stop()
 | 
	
		
			
				|  |  | -        x._monitor = Mock()
 | 
	
		
			
				|  |  | -        x.stop()
 | 
	
		
			
				|  |  | -        x._monitor.stop.assert_called_with()
 |