2018-12-11 07:06:07 +00:00
|
|
|
"""
|
|
|
|
Tests for repo2docker/utils.py
|
|
|
|
"""
|
2018-12-11 07:19:13 +00:00
|
|
|
import traitlets
|
2018-12-11 07:13:56 +00:00
|
|
|
import os
|
2018-12-11 07:06:07 +00:00
|
|
|
from repo2docker import utils
|
|
|
|
import pytest
|
|
|
|
import subprocess
|
2019-08-30 08:06:53 +00:00
|
|
|
import tempfile
|
2018-12-11 07:06:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_capture_cmd_no_capture_success():
|
|
|
|
# This should succeed
|
2019-05-31 09:10:17 +00:00
|
|
|
for line in utils.execute_cmd(["/bin/bash", "-c", "echo test"]):
|
2018-12-11 07:06:07 +00:00
|
|
|
pass
|
|
|
|
|
2018-12-21 12:58:01 +00:00
|
|
|
|
2018-12-11 07:06:07 +00:00
|
|
|
def test_capture_cmd_no_capture_fail():
|
|
|
|
with pytest.raises(subprocess.CalledProcessError):
|
2019-05-31 09:10:17 +00:00
|
|
|
for line in utils.execute_cmd(["/bin/bash", "-c", "e "]):
|
2018-12-11 07:06:07 +00:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def test_capture_cmd_capture_success():
|
|
|
|
# This should succeed
|
2019-05-31 09:10:17 +00:00
|
|
|
for line in utils.execute_cmd(["/bin/bash", "-c", "echo test"], capture=True):
|
|
|
|
assert line == "test\n"
|
2018-12-11 07:06:07 +00:00
|
|
|
|
|
|
|
|
2020-02-16 14:26:54 +00:00
|
|
|
def test_capture_cmd_noeol_capture_success():
|
|
|
|
# This should succeed
|
|
|
|
lines = list(
|
|
|
|
utils.execute_cmd(["/bin/bash", "-c", "echo -en 'test\ntest'"], capture=True)
|
|
|
|
)
|
|
|
|
assert lines == ["test\n", "test"]
|
|
|
|
|
|
|
|
|
2018-12-11 07:06:07 +00:00
|
|
|
def test_capture_cmd_capture_fail():
|
|
|
|
with pytest.raises(subprocess.CalledProcessError):
|
2019-05-31 09:10:17 +00:00
|
|
|
for line in utils.execute_cmd(
|
|
|
|
["/bin/bash", "-c", "echo test; exit 1 "], capture=True
|
|
|
|
):
|
|
|
|
assert line == "test\n"
|
2018-12-11 07:13:56 +00:00
|
|
|
|
|
|
|
|
2018-12-17 12:11:45 +00:00
|
|
|
def test_chdir(tmpdir):
|
2019-05-31 09:10:17 +00:00
|
|
|
d = str(tmpdir.mkdir("cwd"))
|
2018-12-17 12:11:45 +00:00
|
|
|
cur_cwd = os.getcwd()
|
|
|
|
with utils.chdir(d):
|
|
|
|
assert os.getcwd() == d
|
|
|
|
assert os.getcwd() == cur_cwd
|
2018-12-11 07:19:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_byte_spec_validation():
|
|
|
|
bs = utils.ByteSpecification()
|
|
|
|
|
|
|
|
assert bs.validate(None, 1) == 1
|
|
|
|
assert bs.validate(None, 1.0) == 1.0
|
|
|
|
|
2019-05-31 09:10:17 +00:00
|
|
|
assert bs.validate(None, "1K") == 1024
|
|
|
|
assert bs.validate(None, "1M") == 1024 * 1024
|
|
|
|
assert bs.validate(None, "1G") == 1024 * 1024 * 1024
|
|
|
|
assert bs.validate(None, "1T") == 1024 * 1024 * 1024 * 1024
|
2018-12-11 07:19:13 +00:00
|
|
|
|
|
|
|
with pytest.raises(traitlets.TraitError):
|
2019-05-31 09:10:17 +00:00
|
|
|
bs.validate(None, "NK")
|
2018-12-11 07:19:13 +00:00
|
|
|
|
|
|
|
with pytest.raises(traitlets.TraitError):
|
2019-05-31 09:10:17 +00:00
|
|
|
bs.validate(None, "1m")
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"input,expected",
|
|
|
|
[
|
|
|
|
(["8888:8888"], {"8888/tcp": "8888"}),
|
|
|
|
(["8888:4321"], {"4321/tcp": "8888"}),
|
|
|
|
(["8888:4321/udp"], {"4321/udp": "8888"}),
|
|
|
|
(["8888:4321/udp", "8888:4321/tcp"], {"4321/udp": "8888", "4321/tcp": "8888"}),
|
|
|
|
(["127.0.0.1:80:8000"], {"8000/tcp": ("127.0.0.1", "80")}),
|
|
|
|
(["8888:4321", "1234:12345"], {"4321/tcp": "8888", "12345/tcp": "1234"}),
|
|
|
|
],
|
|
|
|
)
|
2018-12-21 12:58:01 +00:00
|
|
|
def test_valid_port_mapping(input, expected):
|
|
|
|
actual = utils.validate_and_generate_port_mapping(input)
|
|
|
|
assert actual == expected
|
2018-12-21 15:08:49 +00:00
|
|
|
|
|
|
|
|
2019-05-31 09:10:17 +00:00
|
|
|
@pytest.mark.parametrize("port_spec", ["a8888:8888", "888:888/abc"])
|
2018-12-21 15:08:49 +00:00
|
|
|
def test_invalid_port_mapping(port_spec):
|
|
|
|
with pytest.raises(ValueError) as e:
|
|
|
|
utils.validate_and_generate_port_mapping([port_spec])
|
|
|
|
|
|
|
|
assert 'Port specification "{}"'.format(port_spec) in str(e.value)
|
2019-06-20 20:22:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_deep_get():
|
|
|
|
data = {"data": {"files": [1, 2, 3]}}
|
|
|
|
assert utils.deep_get(data, "data.files.0") == 1
|
|
|
|
assert utils.deep_get(data, "data.files.1") == 2
|
|
|
|
assert utils.deep_get(data, "data.files") == [1, 2, 3]
|
|
|
|
assert utils.deep_get(data, "data") == {"files": [1, 2, 3]}
|
|
|
|
|
|
|
|
|
|
|
|
def test_is_doi():
|
|
|
|
assert utils.is_doi("10.1234/jshd123") != None
|
|
|
|
assert utils.is_doi("10.1234/JSHD.8192") != None
|
|
|
|
assert utils.is_doi("doi.org/10.1234/jshd123") != None
|
|
|
|
assert utils.is_doi("http://doi.org/10.1234/jshd123") != None
|
|
|
|
assert utils.is_doi("https://doi.org/10.1234/jshd123") != None
|
|
|
|
assert utils.is_doi("http://dx.doi.org/10.1234/jshd123") != None
|
|
|
|
assert utils.is_doi("101234/jshd123") == None
|
|
|
|
assert utils.is_doi("https://mybinder.org") == None
|
|
|
|
|
|
|
|
|
|
|
|
def test_normalize_doi():
|
|
|
|
assert utils.normalize_doi("10.1234/jshd123") == "10.1234/jshd123"
|
|
|
|
assert utils.normalize_doi("10.1234/JSHD.8192") == "10.1234/JSHD.8192"
|
|
|
|
assert utils.normalize_doi("doi.org/10.1234/jshd123") == "10.1234/jshd123"
|
|
|
|
assert utils.normalize_doi("http://doi.org/10.1234/jshd123") == "10.1234/jshd123"
|
|
|
|
assert utils.normalize_doi("https://doi.org/10.1234/jshd123") == "10.1234/jshd123"
|
|
|
|
assert utils.normalize_doi("http://dx.doi.org/10.1234/jshd123") == "10.1234/jshd123"
|
2019-07-18 12:40:17 +00:00
|
|
|
|
|
|
|
|
2019-08-30 08:06:53 +00:00
|
|
|
def test_open_guess_encoding():
|
|
|
|
data = "Rică nu știa să zică râu, rățușcă, rămurică."
|
2019-08-30 08:26:48 +00:00
|
|
|
with tempfile.NamedTemporaryFile(mode="wb") as test_file:
|
2019-08-30 08:06:53 +00:00
|
|
|
test_file.write(str.encode(data, "utf-16"))
|
|
|
|
test_file.seek(0)
|
|
|
|
with utils.open_guess_encoding(test_file.name) as fd:
|
|
|
|
assert fd.read() == data
|
|
|
|
|
2019-08-30 08:26:48 +00:00
|
|
|
|
2019-07-18 12:40:17 +00:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"req, is_local",
|
|
|
|
[
|
|
|
|
("-r requirements.txt", True),
|
|
|
|
("-e .", True),
|
2020-03-27 14:28:19 +00:00
|
|
|
("--editable=.", True),
|
2020-03-27 14:32:00 +00:00
|
|
|
(
|
|
|
|
"--editable=git+https://github.com/popgensims/stdpopsim.git#egg=stdpopsim-master",
|
|
|
|
False,
|
|
|
|
),
|
2019-07-18 12:40:17 +00:00
|
|
|
("file://subdir", True),
|
|
|
|
("file://./subdir", True),
|
2020-08-10 07:33:05 +00:00
|
|
|
("git://github.com/jupyterhub/repo2docker", False),
|
|
|
|
("git+https://github.com/jupyterhub/repo2docker", False),
|
2019-07-18 12:40:17 +00:00
|
|
|
("numpy", False),
|
|
|
|
("# -e .", False),
|
2020-08-13 12:00:16 +00:00
|
|
|
("--pre", False),
|
2020-08-13 12:29:50 +00:00
|
|
|
# pip ignores the package name and treats this like `--pre` on a line
|
|
|
|
# by itself
|
2020-08-13 12:00:16 +00:00
|
|
|
("--pre pandas", False),
|
2020-08-13 12:29:50 +00:00
|
|
|
# These are invalid lines as far as pip is concerned, check that our
|
|
|
|
# code is robust and continues running
|
2020-08-17 06:01:20 +00:00
|
|
|
("--unrecognized", False),
|
|
|
|
("-e", False),
|
2019-07-18 12:40:17 +00:00
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_local_pip_requirement(req, is_local):
|
|
|
|
assert utils.is_local_pip_requirement(req) == is_local
|