mirror of
				https://github.com/django/daphne.git
				synced 2025-11-04 01:27:33 +03:00 
			
		
		
		
	* Add tests for runserver and runworker management commands * Fix flake8 and isort errors * Refactor mocking, add comments to tests * rm unneeded vargs
		
			
				
	
	
		
			159 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			159 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from __future__ import unicode_literals
 | 
						|
 | 
						|
import logging
 | 
						|
 | 
						|
from asgiref.inmemory import ChannelLayer
 | 
						|
from django.core.management import CommandError, call_command
 | 
						|
from channels.staticfiles import StaticFilesConsumer
 | 
						|
from django.test import TestCase, mock
 | 
						|
from six import StringIO
 | 
						|
 | 
						|
from channels.management.commands import runserver
 | 
						|
 | 
						|
 | 
						|
class FakeChannelLayer(ChannelLayer):
 | 
						|
    '''
 | 
						|
    Dummy class to bypass the 'inmemory' string check.
 | 
						|
    '''
 | 
						|
    pass
 | 
						|
 | 
						|
 | 
						|
@mock.patch('channels.management.commands.runworker.Worker')
 | 
						|
class RunWorkerTests(TestCase):
 | 
						|
 | 
						|
    def setUp(self):
 | 
						|
        import channels.log
 | 
						|
        self.stream = StringIO()
 | 
						|
        channels.log.handler = logging.StreamHandler(self.stream)
 | 
						|
 | 
						|
    def test_runworker_no_local_only(self, mock_worker):
 | 
						|
        """
 | 
						|
        Runworker should fail with the default "inmemory" worker.
 | 
						|
        """
 | 
						|
        with self.assertRaises(CommandError):
 | 
						|
            call_command('runworker')
 | 
						|
 | 
						|
    def test_debug(self, mock_worker):
 | 
						|
        """
 | 
						|
        Test that the StaticFilesConsumer is used in debug mode.
 | 
						|
        """
 | 
						|
        with self.settings(DEBUG=True, STATIC_URL='/static/'):
 | 
						|
            # Use 'fake_channel' that bypasses the 'inmemory' check
 | 
						|
            call_command('runworker', '--layer', 'fake_channel')
 | 
						|
            mock_worker.assert_called_with(
 | 
						|
                only_channels=None, exclude_channels=None, callback=None, channel_layer=mock.ANY)
 | 
						|
 | 
						|
            channel_layer = mock_worker.call_args[1]['channel_layer']
 | 
						|
            static_consumer = channel_layer.router.root.routing[0].consumer
 | 
						|
            self.assertIsInstance(static_consumer, StaticFilesConsumer)
 | 
						|
 | 
						|
    def test_runworker(self, mock_worker):
 | 
						|
        # Use 'fake_channel' that bypasses the 'inmemory' check
 | 
						|
        call_command('runworker', '--layer', 'fake_channel')
 | 
						|
        mock_worker.assert_called_with(callback=None,
 | 
						|
                                       only_channels=None,
 | 
						|
                                       channel_layer=mock.ANY,
 | 
						|
                                       exclude_channels=None)
 | 
						|
 | 
						|
    def test_runworker_verbose(self, mocked_worker):
 | 
						|
        # Use 'fake_channel' that bypasses the 'inmemory' check
 | 
						|
        call_command('runworker', '--layer',
 | 
						|
                     'fake_channel', '--verbosity', '2')
 | 
						|
 | 
						|
        # Verify the callback is set
 | 
						|
        mocked_worker.assert_called_with(callback=mock.ANY,
 | 
						|
                                         only_channels=None,
 | 
						|
                                         channel_layer=mock.ANY,
 | 
						|
                                         exclude_channels=None)
 | 
						|
 | 
						|
 | 
						|
class RunServerTests(TestCase):
 | 
						|
 | 
						|
    def setUp(self):
 | 
						|
        import channels.log
 | 
						|
        self.stream = StringIO()
 | 
						|
        # Capture the logging of the channels moduel to match against the
 | 
						|
        # output.
 | 
						|
        channels.log.handler = logging.StreamHandler(self.stream)
 | 
						|
 | 
						|
    @mock.patch('channels.management.commands.runserver.sys.stdout', new_callable=StringIO)
 | 
						|
    @mock.patch('channels.management.commands.runserver.Server')
 | 
						|
    @mock.patch('channels.management.commands.runworker.Worker')
 | 
						|
    def test_runserver_basic(self, mocked_worker, mocked_server, mock_stdout):
 | 
						|
        # Django's autoreload util uses threads and this is not needed
 | 
						|
        # in the test envirionment.
 | 
						|
        # See:
 | 
						|
        # https://github.com/django/django/blob/master/django/core/management/commands/runserver.py#L105
 | 
						|
        call_command('runserver', '--noreload')
 | 
						|
        mocked_server.assert_called_with(port=8000, signal_handlers=True, http_timeout=60,
 | 
						|
                                         host='127.0.0.1', action_logger=mock.ANY, channel_layer=mock.ANY)
 | 
						|
 | 
						|
    @mock.patch('channels.management.commands.runserver.sys.stdout', new_callable=StringIO)
 | 
						|
    @mock.patch('channels.management.commands.runserver.Server')
 | 
						|
    @mock.patch('channels.management.commands.runworker.Worker')
 | 
						|
    def test_runserver_debug(self, mocked_worker, mocked_server, mock_stdout):
 | 
						|
        """
 | 
						|
        Test that the server runs with `DEBUG=True`.
 | 
						|
        """
 | 
						|
        # Debug requires the static url is set.
 | 
						|
        with self.settings(DEBUG=True, STATIC_URL='/static/'):
 | 
						|
            call_command('runserver', '--noreload')
 | 
						|
            mocked_server.assert_called_with(port=8000, signal_handlers=True, http_timeout=60,
 | 
						|
                                             host='127.0.0.1', action_logger=mock.ANY, channel_layer=mock.ANY)
 | 
						|
 | 
						|
            call_command('runserver', '--noreload', 'localhost:8001')
 | 
						|
            mocked_server.assert_called_with(port=8001, signal_handlers=True, http_timeout=60,
 | 
						|
                                             host='localhost', action_logger=mock.ANY, channel_layer=mock.ANY)
 | 
						|
 | 
						|
        self.assertFalse(mocked_worker.called,
 | 
						|
                         "The worker should not be called with '--noworker'")
 | 
						|
 | 
						|
    @mock.patch('channels.management.commands.runserver.sys.stdout', new_callable=StringIO)
 | 
						|
    @mock.patch('channels.management.commands.runserver.Server')
 | 
						|
    @mock.patch('channels.management.commands.runworker.Worker')
 | 
						|
    def test_runserver_noworker(self, mocked_worker, mocked_server, mock_stdout):
 | 
						|
        '''
 | 
						|
        Test that the Worker is not called when using the `--noworker` parameter.
 | 
						|
        '''
 | 
						|
        call_command('runserver', '--noreload', '--noworker')
 | 
						|
        mocked_server.assert_called_with(port=8000, signal_handlers=True, http_timeout=60,
 | 
						|
                                         host='127.0.0.1', action_logger=mock.ANY, channel_layer=mock.ANY)
 | 
						|
        self.assertFalse(mocked_worker.called,
 | 
						|
                         "The worker should not be called with '--noworker'")
 | 
						|
 | 
						|
    @mock.patch('channels.management.commands.runserver.sys.stderr', new_callable=StringIO)
 | 
						|
    def test_log_action(self, mocked_stderr):
 | 
						|
        cmd = runserver.Command()
 | 
						|
        test_actions = [
 | 
						|
            (100, 'http', 'complete',
 | 
						|
             'HTTP GET /a-path/ 100 [0.12, a-client]'),
 | 
						|
            (200, 'http', 'complete',
 | 
						|
             'HTTP GET /a-path/ 200 [0.12, a-client]'),
 | 
						|
            (300, 'http', 'complete',
 | 
						|
             'HTTP GET /a-path/ 300 [0.12, a-client]'),
 | 
						|
            (304, 'http', 'complete',
 | 
						|
             'HTTP GET /a-path/ 304 [0.12, a-client]'),
 | 
						|
            (400, 'http', 'complete',
 | 
						|
             'HTTP GET /a-path/ 400 [0.12, a-client]'),
 | 
						|
            (404, 'http', 'complete',
 | 
						|
             'HTTP GET /a-path/ 404 [0.12, a-client]'),
 | 
						|
            (500, 'http', 'complete',
 | 
						|
             'HTTP GET /a-path/ 500 [0.12, a-client]'),
 | 
						|
            (None, 'websocket', 'connected',
 | 
						|
             'WebSocket CONNECT /a-path/ [a-client]'),
 | 
						|
            (None, 'websocket', 'disconnected',
 | 
						|
             'WebSocket DISCONNECT /a-path/ [a-client]'),
 | 
						|
            (None, 'websocket', 'something', ''),  # This shouldn't happen
 | 
						|
        ]
 | 
						|
 | 
						|
        for status_code, protocol, action, output in test_actions:
 | 
						|
            details = {'status': status_code,
 | 
						|
                       'method': 'GET',
 | 
						|
                       'path': '/a-path/',
 | 
						|
                       'time_taken': 0.12345,
 | 
						|
                       'client': 'a-client'}
 | 
						|
            cmd.log_action(protocol, action, details)
 | 
						|
            self.assertIn(output, mocked_stderr.getvalue())
 | 
						|
            # Clear previous output
 | 
						|
            mocked_stderr.truncate(0)
 |