increase some test coverage

This commit is contained in:
Min RK
2016-03-07 16:13:57 +01:00
parent 9af103c673
commit 67ccfc7eb7
6 changed files with 193 additions and 9 deletions

View File

@@ -111,6 +111,8 @@ class MockHub(JupyterHub):
db_file = None
confirm_no_ssl = True
last_activity_interval = 2
def _subdomain_host_default(self):
return os.environ.get('JUPYTERHUB_TEST_SUBDOMAIN_HOST', '')
@@ -128,7 +130,8 @@ class MockHub(JupyterHub):
def start(self, argv=None):
self.db_file = NamedTemporaryFile()
self.db_url = 'sqlite:///' + self.db_file.name
self.pid_file = NamedTemporaryFile(delete=False).name
self.db_url = self.db_file.name
evt = threading.Event()
@@ -173,6 +176,7 @@ class MockHub(JupyterHub):
},
allow_redirects=False,
)
r.raise_for_status()
assert r.cookies
return r.cookies

View File

@@ -3,7 +3,7 @@
import json
import time
from queue import Queue
from urllib.parse import urlparse
from urllib.parse import urlparse, quote
import requests
@@ -383,6 +383,7 @@ def test_slow_spawn(app, io_loop):
name = 'zoe'
user = add_user(db, app=app, name=name)
r = api_request(app, 'users', name, 'server', method='post')
app.tornado_settings['spawner_class'] = mocking.MockSpawner
r.raise_for_status()
assert r.status_code == 202
app_user = get_app_user(app, name)
@@ -432,6 +433,7 @@ def test_never_spawn(app, io_loop):
name = 'badger'
user = add_user(db, app=app, name=name)
r = api_request(app, 'users', name, 'server', method='post')
app.tornado_settings['spawner_class'] = mocking.MockSpawner
app_user = get_app_user(app, name)
assert app_user.spawner is not None
assert app_user.spawn_pending
@@ -454,6 +456,55 @@ def test_get_proxy(app, io_loop):
assert list(reply.keys()) == ['/']
def test_cookie(app):
db = app.db
name = 'patience'
user = add_user(db, app=app, name=name)
r = api_request(app, 'users', name, 'server', method='post')
assert r.status_code == 201
assert 'pid' in user.state
app_user = get_app_user(app, name)
cookies = app.login_user(name)
# cookie jar gives '"cookie-value"', we want 'cookie-value'
cookie = cookies[user.server.cookie_name][1:-1]
r = api_request(app, 'authorizations/cookie', user.server.cookie_name, "nothintoseehere")
assert r.status_code == 404
r = api_request(app, 'authorizations/cookie', user.server.cookie_name, quote(cookie, safe=''))
r.raise_for_status()
reply = r.json()
assert reply['name'] == name
# deprecated cookie in body:
r = api_request(app, 'authorizations/cookie', user.server.cookie_name, data=cookie)
r.raise_for_status()
reply = r.json()
assert reply['name'] == name
def test_token(app):
name = 'book'
user = add_user(app.db, app=app, name=name)
token = user.new_api_token()
r = api_request(app, 'authorizations/token', token)
r.raise_for_status()
user_model = r.json()
assert user_model['name'] == name
r = api_request(app, 'authorizations/token', 'notauthorized')
assert r.status_code == 404
def test_options(app):
r = api_request(app, 'users', method='options')
r.raise_for_status()
assert 'Access-Control-Allow-Headers' in r.headers
def test_bad_json_body(app):
r = api_request(app, 'users', method='post', data='notjson')
assert r.status_code == 400
def test_shutdown(app):
r = api_request(app, 'shutdown', method='post', data=json.dumps({
'servers': True,

View File

@@ -3,8 +3,9 @@
import os
import re
import sys
from subprocess import check_output
from subprocess import check_output, Popen, PIPE
from tempfile import NamedTemporaryFile, TemporaryDirectory
from .mocking import MockHub
def test_help_all():
out = check_output([sys.executable, '-m', 'jupyterhub', '--help-all']).decode('utf8', 'replace')
@@ -23,10 +24,23 @@ def test_token_app():
def test_generate_config():
with NamedTemporaryFile(prefix='jupyterhub_config', suffix='.py') as tf:
cfg_file = tf.name
with open(cfg_file, 'w') as f:
f.write("c.A = 5")
p = Popen([sys.executable, '-m', 'jupyterhub',
'--generate-config', '-f', cfg_file],
stdout=PIPE, stdin=PIPE)
out, _ = p.communicate(b'n')
out = out.decode('utf8', 'replace')
assert os.path.exists(cfg_file)
with open(cfg_file) as f:
cfg_text = f.read()
assert cfg_text == 'c.A = 5'
out = check_output([sys.executable, '-m', 'jupyterhub',
'--generate-config', '-f', cfg_file]
).decode('utf8', 'replace')
p = Popen([sys.executable, '-m', 'jupyterhub',
'--generate-config', '-f', cfg_file],
stdout=PIPE, stdin=PIPE)
out, _ = p.communicate(b'x\ny')
out = out.decode('utf8', 'replace')
assert os.path.exists(cfg_file)
with open(cfg_file) as f:
cfg_text = f.read()

View File

@@ -63,6 +63,7 @@ def test_admin(app):
r.raise_for_status()
assert r.url.endswith('/admin')
def test_spawn_redirect(app, io_loop):
name = 'wash'
cookies = app.login_user(name)
@@ -174,6 +175,53 @@ def test_user_redirect(app):
assert query == urlencode({'next': '/hub/user/baduser/test.ipynb'})
def test_login_fail(app):
name = 'wash'
base_url = public_url(app)
r = requests.post(base_url + 'hub/login',
data={
'username': name,
'password': 'wrong',
},
allow_redirects=False,
)
assert not r.cookies
def test_login_redirect(app, io_loop):
cookies = app.login_user('river')
user = app.users['river']
# no next_url, server running
io_loop.run_sync(user.spawn)
r = get_page('login', app, cookies=cookies, allow_redirects=False)
r.raise_for_status()
assert r.status_code == 302
assert '/user/river' in r.headers['Location']
# no next_url, server not running
io_loop.run_sync(user.stop)
r = get_page('login', app, cookies=cookies, allow_redirects=False)
r.raise_for_status()
assert r.status_code == 302
assert '/hub/' in r.headers['Location']
# next URL given, use it
r = get_page('login?next=/hub/admin', app, cookies=cookies, allow_redirects=False)
r.raise_for_status()
assert r.status_code == 302
assert r.headers['Location'].endswith('/hub/admin')
def test_logout(app):
name = 'wash'
cookies = app.login_user(name)
r = requests.get(public_host(app) + app.tornado_settings['logout_url'], cookies=cookies)
r.raise_for_status()
login_url = public_host(app) + app.tornado_settings['login_url']
assert r.url == login_url
assert r.cookies == {}
def test_static_files(app):
base_url = ujoin(public_url(app), app.hub.server.base_url)
print(base_url)
@@ -186,5 +234,3 @@ def test_static_files(app):
r = requests.get(ujoin(base_url, 'static', 'css', 'style.min.css'))
r.raise_for_status()
assert r.headers['content-type'] == 'text/css'

View File

@@ -105,6 +105,8 @@ def test_external_proxy(request, io_loop):
# tell the hub where the new proxy is
r = api_request(app, 'proxy', method='patch', data=json.dumps({
'port': proxy_port,
'protocol': 'http',
'ip': app.ip,
'auth_token': new_auth_token,
}))
r.raise_for_status()
@@ -123,6 +125,7 @@ def test_external_proxy(request, io_loop):
routes = io_loop.run_sync(app.proxy.get_routes)
assert sorted(routes.keys()) == ['/', user_path]
def test_check_routes(app, io_loop):
proxy = app.proxy
r = api_request(app, 'users/zoe', method='post')
@@ -142,3 +145,13 @@ def test_check_routes(app, io_loop):
after = sorted(io_loop.run_sync(app.proxy.get_routes))
assert zoe.proxy_path in after
assert before == after
def test_patch_proxy_bad_req(app):
r = api_request(app, 'proxy', method='patch')
assert r.status_code == 400
r = api_request(app, 'proxy', method='patch', data='notjson')
assert r.status_code == 400
r = api_request(app, 'proxy', method='patch', data=json.dumps([]))
assert r.status_code == 400

View File

@@ -4,9 +4,14 @@
# Distributed under the terms of the Modified BSD License.
import logging
import os
import signal
import sys
import tempfile
import time
from unittest import mock
from tornado import gen
from .. import spawner as spawnermod
from ..spawner import LocalProcessSpawner
@@ -39,6 +44,7 @@ def new_spawner(db, **kwargs):
kwargs.setdefault('INTERRUPT_TIMEOUT', 1)
kwargs.setdefault('TERM_TIMEOUT', 1)
kwargs.setdefault('KILL_TIMEOUT', 1)
kwargs.setdefault('poll_interval', 1)
return LocalProcessSpawner(db=db, **kwargs)
@@ -110,3 +116,53 @@ def test_stop_spawner_stop_now(db, io_loop):
status = io_loop.run_sync(spawner.poll)
assert status == -signal.SIGTERM
def test_spawner_poll(db, io_loop):
first_spawner = new_spawner(db)
user = first_spawner.user
io_loop.run_sync(first_spawner.start)
proc = first_spawner.proc
status = io_loop.run_sync(first_spawner.poll)
assert status is None
user.state = first_spawner.get_state()
assert 'pid' in user.state
# create a new Spawner, loading from state of previous
spawner = new_spawner(db, user=first_spawner.user)
spawner.start_polling()
# wait for the process to get to the while True: loop
io_loop.run_sync(lambda : gen.sleep(1))
status = io_loop.run_sync(spawner.poll)
assert status is None
# kill the process
proc.terminate()
for i in range(10):
if proc.poll() is None:
time.sleep(1)
else:
break
assert proc.poll() is not None
io_loop.run_sync(lambda : gen.sleep(2))
status = io_loop.run_sync(spawner.poll)
assert status is not None
def test_setcwd():
cwd = os.getcwd()
with tempfile.TemporaryDirectory() as td:
td = os.path.realpath(os.path.abspath(td))
spawnermod._try_setcwd(td)
assert os.path.samefile(os.getcwd(), td)
os.chdir(cwd)
chdir = os.chdir
temp_root = os.path.realpath(os.path.abspath(tempfile.gettempdir()))
def raiser(path):
path = os.path.realpath(os.path.abspath(path))
if not path.startswith(temp_root):
raise OSError(path)
chdir(path)
with mock.patch('os.chdir', raiser):
spawnermod._try_setcwd(cwd)
assert os.getcwd().startswith(temp_root)
os.chdir(cwd)