import os import stat import subprocess import time from ipython_genutils.testing.decorators import skip_win32, onlyif from notebook import DEFAULT_NOTEBOOK_PORT from .launchnotebook import UNIXSocketNotebookTestBase from ..utils import urlencode_unix_socket, urlencode_unix_socket_path @skip_win32 def test_shutdown_sock_server_integration(): sock = UNIXSocketNotebookTestBase.sock url = urlencode_unix_socket(sock).encode() encoded_sock_path = urlencode_unix_socket_path(sock) p = subprocess.Popen( ['jupyter-notebook', '--sock=%s' % sock, '--sock-mode=0700'], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) complete = False for line in iter(p.stderr.readline, b''): print(line.decode()) if url in line: complete = True break assert complete, 'did not find socket URL in stdout when launching notebook' assert encoded_sock_path.encode() in subprocess.check_output(['jupyter-notebook', 'list']) # Ensure umask is properly applied. assert stat.S_IMODE(os.lstat(sock).st_mode) == 0o700 try: subprocess.check_output(['jupyter-notebook', 'stop'], stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: assert 'There is currently no server running on' in e.output.decode() else: raise AssertionError('expected stop command to fail due to target mis-match') assert encoded_sock_path.encode() in subprocess.check_output(['jupyter-notebook', 'list']) subprocess.check_output(['jupyter-notebook', 'stop', sock]) assert encoded_sock_path.encode() not in subprocess.check_output(['jupyter-notebook', 'list']) p.wait() def test_sock_server_validate_sockmode_type(): try: subprocess.check_output( ['jupyter-notebook', '--sock=/tmp/nonexistent', '--sock-mode=badbadbad'], stderr=subprocess.STDOUT ) except subprocess.CalledProcessError as e: assert 'badbadbad' in e.output.decode() else: raise AssertionError('expected execution to fail due to validation of --sock-mode param') def test_sock_server_validate_sockmode_accessible(): try: subprocess.check_output( ['jupyter-notebook', '--sock=/tmp/nonexistent', '--sock-mode=0444'], stderr=subprocess.STDOUT ) except subprocess.CalledProcessError as e: assert '0444' in e.output.decode() else: raise AssertionError('expected execution to fail due to validation of --sock-mode param') def _ensure_stopped(check_msg='There are no running servers'): try: subprocess.check_output( ['jupyter-notebook', 'stop'], stderr=subprocess.STDOUT ) except subprocess.CalledProcessError as e: assert check_msg in e.output.decode() else: raise AssertionError('expected all servers to be stopped') @onlyif(bool(os.environ.get('RUN_NB_INTEGRATION_TESTS', False)), 'for local testing') def test_stop_multi_integration(): """Tests lifecycle behavior for mixed-mode server types w/ default ports. Mostly suitable for local dev testing due to reliance on default port binding. """ TEST_PORT = '9797' MSG_TMPL = 'Shutting down server on {}...' _ensure_stopped() # Default port. p1 = subprocess.Popen( ['jupyter-notebook', '--no-browser'] ) # Unix socket. sock = UNIXSocketNotebookTestBase.sock p2 = subprocess.Popen( ['jupyter-notebook', '--sock=%s' % sock] ) # Specified port p3 = subprocess.Popen( ['jupyter-notebook', '--no-browser', '--port=%s' % TEST_PORT] ) time.sleep(3) assert MSG_TMPL.format(DEFAULT_NOTEBOOK_PORT) in subprocess.check_output( ['jupyter-notebook', 'stop'] ).decode() _ensure_stopped('There is currently no server running on 8888') assert MSG_TMPL.format(sock) in subprocess.check_output( ['jupyter-notebook', 'stop', sock] ).decode() assert MSG_TMPL.format(TEST_PORT) in subprocess.check_output( ['jupyter-notebook', 'stop', TEST_PORT] ).decode() _ensure_stopped() p1.wait() p2.wait() p3.wait() @skip_win32 def test_launch_socket_collision(): """Tests UNIX socket in-use detection for lifecycle correctness.""" sock = UNIXSocketNotebookTestBase.sock check_msg = 'socket %s is already in use' % sock _ensure_stopped() # Start a server. cmd = ['jupyter-notebook', '--sock=%s' % sock] p1 = subprocess.Popen(cmd) time.sleep(3) # Try to start a server bound to the same UNIX socket. try: subprocess.check_output(cmd, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: assert check_msg in e.output.decode() else: raise AssertionError('expected error, instead got %s' % e.output.decode()) # Stop the background server, ensure it's stopped and wait on the process to exit. subprocess.check_call(['jupyter-notebook', 'stop', sock]) _ensure_stopped() p1.wait()