diff --git a/.gitignore b/.gitignore index eb59eb9..3f0d360 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ env.sh # ignore config file at the top-level of the repo # but not sub-dirs /jupyterhub_config.py +/jupyterhub_config_test.py jupyterhub_cookie_secret jupyterhub.sqlite jupyterhub.log @@ -20,3 +21,4 @@ MANIFEST htmlcov whitelist.txt *.swp +*.log diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..94d7a7d --- /dev/null +++ b/Makefile @@ -0,0 +1,65 @@ +# Makefile for building & starting rep-containers +# arguments can be supplied by -e definitions: +# +# TESTS -- list of tests to run +# +# + +SHELL := /bin/bash +OPTIONS := --debug --port 8000 --log-file=jupyterhub.log --no-ssl +TEST_OPTIONS := -s tests -N 2 +TESTS := case_happy_mp + +.PHONY: install reload clean run + + +help: + @echo Usage: make [-e VARIABLE=VALUE] targets + @echo "variables:" + @grep -h "#\s\+\w\+ -- " $(MAKEFILE_LIST) |sed "s/#\s//" + @echo + @echo targets and corresponding dependencies: + @fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' -e 's/^/ /' | sed -e 's/##//' + + +install: ## install everware + npm install + npm install -g configurable-http-proxy + PYTHON_MAJOR=`python -c 'import sys; print(sys.version_info[0])'` ;\ + if [ $${PYTHON_MAJOR} -eq 3 ] ; then \ + PYTHON=python ;\ + PIP=pip ;\ + elif [ -n `which python3` ] ; then \ + PYTHON=python3 ;\ + PIP=pip3 ;\ + else \ + echo "Unable to find python" ;\ + exit 1 ;\ + fi ;\ + $${PIP} install -e . ;\ + $${PYTHON} setup.py css ;\ + $${PYTHON} setup.py js ;\ + + if [ ! -f env.sh ] ; then cp env.sh.orig env.sh ; fi + if [ ! -f jupyterhub_config.py ] ; then cp jupyterhub_config.py.orig jupyterhub_config.py ; fi + if [ ! -f whitelist.txt ] ; then cp whitelist.txt.orig whitelist.txt ; fi + +reload: ## reload everware whitelist + PID=`pgrep -f jupyterhub` ;\ + if [ -z $${PID} ] ; then echo "Cannot find jupyterhub running" ; exit 1 ; fi + pkill -1 -f jupyterhub + +clean: ## clean user base + rm -f jupyterhub.sqlite + +run: clean ## run everware server + source ./env.sh && \ + jupyterhub ${OPTIONS} + +run-test: clean ## run everware instance for testing (no auth) + cat jupyterhub_config.py <(echo c.JupyterHub.authenticator_class = 'dummyauthenticator.DummyAuthenticator') > jupyterhub_config_test.py + source ./env.sh && \ + jupyterhub ${OPTIONS} --config=jupyterhub_config_test.py + +test-client: ## run selenium tests + nose2 ${TEST_OPTIONS} ${TESTS} diff --git a/jupyterhub_config.py.orig b/jupyterhub_config.py.orig index 1c9b13a..c9fe1f2 100644 --- a/jupyterhub_config.py.orig +++ b/jupyterhub_config.py.orig @@ -2,6 +2,7 @@ import os import everware import jupyterhub.handlers.pages import jupyterhub.handlers.base +import dummyauthenticator # TODO: find a way to change default handlers # instead of this shit diff --git a/reload.sh b/reload.sh deleted file mode 100755 index 4d57c0f..0000000 --- a/reload.sh +++ /dev/null @@ -1,4 +0,0 @@ -PID=`pgrep jupyterhub` -[ -z "$PID" ] && echo "Cannot find jupyterhub running" && exit 1 -pkill -1 jupyterhub -echo "Reloaded" diff --git a/requirements.txt b/requirements.txt index c52a3ef..ef25ba2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,3 +6,4 @@ jupyterhub-dummyauthenticator jupyterhub dockerspawner GitPython==1.0.1 +-e git+https://github.com/yuvipanda/jupyterhub-dummy-authenticator.git#egg=Package diff --git a/run.sh b/run.sh deleted file mode 100755 index 3f0b150..0000000 --- a/run.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -set -e - -source ./env.sh -OPTIONS="--debug --port 8000 --log-file=jupyterhub.log --no-ssl" -source ./clean.sh - -jupyterhub $OPTIONS diff --git a/tests/case_happy_mp.py b/tests/case_happy_mp.py new file mode 100644 index 0000000..ee39f9f --- /dev/null +++ b/tests/case_happy_mp.py @@ -0,0 +1,137 @@ +# -*- coding: utf-8 -*- +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.support.ui import Select +from selenium.common.exceptions import NoSuchElementException +from selenium.common.exceptions import NoAlertPresentException +import time +import traceback +import nose2 + + +REPO = "https://github.com/everware/everware-dimuon-example" +# repo = "docker:yandex/rep-tutorial:0.1.3" +# repo = "docker:everware/https_github_com_everware_everware_dimuon_example-5e87f9567d33842e12636038d56544d54c3d0702" +# repo = "docker:everware/https_github_com_everware_everware_dimuon_example-9bec6770485eb6b245648bc251d045a204973cc9" +# REPO = "docker:yandex/rep-tutorial" + +DRIVER = "phantomjs" +# DRIVER = "firefox" + +class User: + def __init__(self, login=None, repo=REPO, driver_type=DRIVER): + self.login = login + self.repo = repo + self.password = "" + self.log("init") + + self.driver_type = driver_type + self.base_url = "http://localhost:8000/" + self.verificationErrors = [] + self.accept_next_alert = True + + + def get_driver(self): + if self.driver_type == "phantomjs": + self.driver = webdriver.PhantomJS('/usr/local/bin/phantomjs') + if self.driver_type == "firefox": + self.driver = webdriver.Firefox() + self.driver.implicitly_wait(30) + return self.driver + + + def tearDown(self): + self.driver.quit() + # return self.verificationErrors + + def log(self, message): + print("{}: {}".format(self.login, message)) + + + def wait_for_element_present(self, how, what, displayed=True, timeout=30): + for i in range(timeout): + element = self.driver.find_element(by=how, value=what) + if element is not None and element.is_displayed() == displayed: break + time.sleep(1) + else: assert False, "time out waiting for (%s, %s)" % (how, what) + + + def wait_for_element_id_is_gone(self, value, timeout=30): + for i in range(timeout): + try: + element = self.driver.find_element_by_id(value) + except NoSuchElementException as e: + break + time.sleep(1) + # self.log("waiting for %s to go %d" % (value, i)) + else: self.fail("time out wairing for (%s) to disappear" % (what)) + self.log("gone finally (%d)" % i) + + + def is_element_present(self, how, what): + try: self.driver.find_element(by=how, value=what) + except NoSuchElementException as e: return False + return True + + +def test_generator(): + for scenario in ["scenario_short"]: + for username in ["an1", "an2"]: + # for username in ["an1"]: + yield scenario_runner, scenario, username + + +def scenario_runner(scenario, username): + user = User(username) + try: + globals()[scenario](user) + except Exception as e: + print("oops: %s" % repr(e)) + assert False, traceback.format_stack() + finally: + user.tearDown() + + +def scenario_short(user): + driver = user.get_driver() + driver.get(user.base_url + "/hub/login") + user.log("login") + driver.find_element_by_id("username_input").clear() + driver.find_element_by_id("username_input").send_keys(user.login) + driver.find_element_by_id("password_input").clear() + driver.find_element_by_id("password_input").send_keys(user.password) + driver.find_element_by_id("login_submit").click() + user.wait_for_element_present(By.ID, "start") + driver.find_element_by_id("logout").click() + user.log("logout clicked") + + +def scenario_full(user): + driver = user.get_driver() + driver.get(user.base_url + "/hub/login") + user.log("login") + driver.find_element_by_id("username_input").clear() + driver.find_element_by_id("username_input").send_keys(user.login) + driver.find_element_by_id("password_input").clear() + driver.find_element_by_id("password_input").send_keys(user.password) + driver.find_element_by_id("login_submit").click() + user.wait_for_element_present(By.ID, "start") + driver.find_element_by_id("start").click() + driver.find_element_by_id("repository_input").clear() + driver.find_element_by_id("repository_input").send_keys(user.repo) + driver.find_element_by_xpath("//input[@value='Spawn']").click() + user.log("start clicked") + user.wait_for_element_present(By.LINK_TEXT, "Control Panel") + driver.find_element_by_link_text("Control Panel").click() + user.wait_for_element_present(By.ID, "stop") + driver.find_element_by_id("stop").click() + user.log("stop clicked") + user.wait_for_element_present(By.ID, "wait") + user.log("waiting to stop") + user.wait_for_element_id_is_gone("wait") + driver.find_element_by_id("logout").click() + user.log("logout clicked") + +if __name__ == "__main__": + nose2.main() diff --git a/unittest.cfg b/unittest.cfg new file mode 100644 index 0000000..835e497 --- /dev/null +++ b/unittest.cfg @@ -0,0 +1,7 @@ +[unittest] +plugins = nose2.plugins.mp + +[multiprocess] +always-on = False +processes = 2 +test-run-timeout = 60.0