2019-05-15 06:56:31 +08:00
|
|
|
# -*- coding: utf-8 -*-
|
2018-10-25 15:01:29 +08:00
|
|
|
from __future__ import absolute_import
|
|
|
|
from __future__ import division
|
|
|
|
from __future__ import print_function
|
|
|
|
|
2015-09-17 00:06:39 +08:00
|
|
|
import sys
|
2018-10-15 05:21:04 +08:00
|
|
|
|
2018-11-20 20:47:40 +08:00
|
|
|
import attr
|
2018-10-15 05:21:04 +08:00
|
|
|
import six
|
|
|
|
|
2014-01-29 17:20:13 +08:00
|
|
|
import pytest
|
2018-10-24 13:45:53 +08:00
|
|
|
from _pytest import pathlib
|
2018-10-15 05:21:04 +08:00
|
|
|
from _pytest.pathlib import Path
|
2018-11-09 06:14:58 +08:00
|
|
|
from _pytest.warnings import SHOW_PYTEST_WARNINGS_ARG
|
2010-10-10 19:48:49 +08:00
|
|
|
|
2009-09-06 22:59:39 +08:00
|
|
|
|
2018-07-22 22:10:44 +08:00
|
|
|
def test_tmpdir_fixture(testdir):
|
2018-07-27 07:10:40 +08:00
|
|
|
p = testdir.copy_example("tmpdir/tmpdir_fixture.py")
|
|
|
|
results = testdir.runpytest(p)
|
2019-03-23 18:36:18 +08:00
|
|
|
results.stdout.fnmatch_lines(["*1 passed*"])
|
2010-10-10 19:48:49 +08:00
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2010-10-10 19:48:49 +08:00
|
|
|
def test_ensuretemp(recwarn):
|
2018-05-23 22:48:46 +08:00
|
|
|
d1 = pytest.ensuretemp("hello")
|
|
|
|
d2 = pytest.ensuretemp("hello")
|
2010-10-10 19:48:49 +08:00
|
|
|
assert d1 == d2
|
|
|
|
assert d1.check(dir=1)
|
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2018-11-20 20:47:40 +08:00
|
|
|
@attr.s
|
|
|
|
class FakeConfig(object):
|
|
|
|
basetemp = attr.ib()
|
|
|
|
trace = attr.ib(default=None)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def trace(self):
|
|
|
|
return self
|
|
|
|
|
|
|
|
def get(self, key):
|
|
|
|
return lambda *k: None
|
|
|
|
|
|
|
|
@property
|
|
|
|
def option(self):
|
|
|
|
return self
|
|
|
|
|
|
|
|
|
2017-02-17 02:41:51 +08:00
|
|
|
class TestTempdirHandler(object):
|
2018-11-20 20:47:40 +08:00
|
|
|
def test_mktemp(self, tmp_path):
|
|
|
|
|
2018-09-16 04:30:44 +08:00
|
|
|
from _pytest.tmpdir import TempdirFactory, TempPathFactory
|
2018-05-23 22:48:46 +08:00
|
|
|
|
2018-11-20 20:47:40 +08:00
|
|
|
config = FakeConfig(tmp_path)
|
2018-09-16 04:30:44 +08:00
|
|
|
t = TempdirFactory(TempPathFactory.from_config(config))
|
2010-11-22 00:43:18 +08:00
|
|
|
tmp = t.mktemp("world")
|
|
|
|
assert tmp.relto(t.getbasetemp()) == "world0"
|
|
|
|
tmp = t.mktemp("this")
|
|
|
|
assert tmp.relto(t.getbasetemp()).startswith("this")
|
|
|
|
tmp2 = t.mktemp("this")
|
|
|
|
assert tmp2.relto(t.getbasetemp()).startswith("this")
|
|
|
|
assert tmp2 != tmp
|
|
|
|
|
2018-11-20 20:47:40 +08:00
|
|
|
def test_tmppath_relative_basetemp_absolute(self, tmp_path, monkeypatch):
|
2019-04-27 22:25:37 +08:00
|
|
|
"""#4425"""
|
2018-11-20 20:47:40 +08:00
|
|
|
from _pytest.tmpdir import TempPathFactory
|
|
|
|
|
|
|
|
monkeypatch.chdir(tmp_path)
|
|
|
|
config = FakeConfig("hello")
|
|
|
|
t = TempPathFactory.from_config(config)
|
2018-11-22 23:10:12 +08:00
|
|
|
assert t.getbasetemp().resolve() == (tmp_path / "hello").resolve()
|
2018-11-20 20:47:40 +08:00
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2017-02-17 02:41:51 +08:00
|
|
|
class TestConfigTmpdir(object):
|
2010-11-22 00:43:18 +08:00
|
|
|
def test_getbasetemp_custom_removes_old(self, testdir):
|
2015-07-16 07:03:58 +08:00
|
|
|
mytemp = testdir.tmpdir.join("xyz")
|
2018-05-23 22:48:46 +08:00
|
|
|
p = testdir.makepyfile(
|
|
|
|
"""
|
2015-07-16 07:03:58 +08:00
|
|
|
def test_1(tmpdir):
|
|
|
|
pass
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
|
|
|
)
|
|
|
|
testdir.runpytest(p, "--basetemp=%s" % mytemp)
|
2015-07-16 07:03:58 +08:00
|
|
|
mytemp.check()
|
|
|
|
mytemp.ensure("hello")
|
|
|
|
|
2018-05-23 22:48:46 +08:00
|
|
|
testdir.runpytest(p, "--basetemp=%s" % mytemp)
|
2015-07-16 07:03:58 +08:00
|
|
|
mytemp.check()
|
|
|
|
assert not mytemp.join("hello").check()
|
|
|
|
|
2010-11-22 00:43:18 +08:00
|
|
|
|
|
|
|
def test_basetemp(testdir):
|
|
|
|
mytemp = testdir.tmpdir.mkdir("mytemp")
|
2018-05-23 22:48:46 +08:00
|
|
|
p = testdir.makepyfile(
|
|
|
|
"""
|
2010-11-22 00:43:18 +08:00
|
|
|
import pytest
|
|
|
|
def test_1():
|
|
|
|
pytest.ensuretemp("hello")
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
|
|
|
)
|
2018-11-09 06:14:58 +08:00
|
|
|
result = testdir.runpytest(p, "--basetemp=%s" % mytemp, SHOW_PYTEST_WARNINGS_ARG)
|
2010-11-22 00:43:18 +08:00
|
|
|
assert result.ret == 0
|
2018-05-23 22:48:46 +08:00
|
|
|
assert mytemp.join("hello").check()
|
2011-11-07 03:34:02 +08:00
|
|
|
|
2017-07-17 07:25:09 +08:00
|
|
|
|
2012-10-11 19:05:16 +08:00
|
|
|
def test_tmpdir_always_is_realpath(testdir):
|
|
|
|
# the reason why tmpdir should be a realpath is that
|
|
|
|
# when you cd to it and do "os.getcwd()" you will anyway
|
|
|
|
# get the realpath. Using the symlinked path can thus
|
|
|
|
# easily result in path-inequality
|
|
|
|
# XXX if that proves to be a problem, consider using
|
|
|
|
# os.environ["PWD"]
|
2011-11-07 03:34:02 +08:00
|
|
|
realtemp = testdir.tmpdir.mkdir("myrealtemp")
|
|
|
|
linktemp = testdir.tmpdir.join("symlinktemp")
|
2018-10-15 05:21:04 +08:00
|
|
|
attempt_symlink_to(linktemp, str(realtemp))
|
2018-05-23 22:48:46 +08:00
|
|
|
p = testdir.makepyfile(
|
|
|
|
"""
|
2011-11-07 03:34:02 +08:00
|
|
|
def test_1(tmpdir):
|
|
|
|
import os
|
2012-10-11 19:05:16 +08:00
|
|
|
assert os.path.realpath(str(tmpdir)) == str(tmpdir)
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
|
|
|
)
|
|
|
|
result = testdir.runpytest("-s", p, "--basetemp=%s/bt" % linktemp)
|
2011-11-07 03:34:02 +08:00
|
|
|
assert not result.ret
|
2012-10-11 19:05:16 +08:00
|
|
|
|
2015-07-29 07:35:13 +08:00
|
|
|
|
2019-01-19 04:54:00 +08:00
|
|
|
def test_tmp_path_always_is_realpath(testdir, monkeypatch):
|
|
|
|
# for reasoning see: test_tmpdir_always_is_realpath test-case
|
|
|
|
realtemp = testdir.tmpdir.mkdir("myrealtemp")
|
|
|
|
linktemp = testdir.tmpdir.join("symlinktemp")
|
|
|
|
attempt_symlink_to(linktemp, str(realtemp))
|
|
|
|
monkeypatch.setenv("PYTEST_DEBUG_TEMPROOT", str(linktemp))
|
|
|
|
testdir.makepyfile(
|
|
|
|
"""
|
|
|
|
def test_1(tmp_path):
|
|
|
|
assert tmp_path.resolve() == tmp_path
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
reprec = testdir.inline_run()
|
|
|
|
reprec.assertoutcome(passed=1)
|
|
|
|
|
|
|
|
|
2013-10-03 20:22:54 +08:00
|
|
|
def test_tmpdir_too_long_on_parametrization(testdir):
|
2018-05-23 22:48:46 +08:00
|
|
|
testdir.makepyfile(
|
|
|
|
"""
|
2013-10-03 20:22:54 +08:00
|
|
|
import pytest
|
|
|
|
@pytest.mark.parametrize("arg", ["1"*1000])
|
|
|
|
def test_some(arg, tmpdir):
|
|
|
|
tmpdir.ensure("hello")
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
|
|
|
)
|
2013-10-03 20:22:54 +08:00
|
|
|
reprec = testdir.inline_run()
|
|
|
|
reprec.assertoutcome(passed=1)
|
2015-07-29 07:35:13 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_tmpdir_factory(testdir):
|
2018-05-23 22:48:46 +08:00
|
|
|
testdir.makepyfile(
|
|
|
|
"""
|
2015-07-29 07:35:13 +08:00
|
|
|
import pytest
|
|
|
|
@pytest.fixture(scope='session')
|
|
|
|
def session_dir(tmpdir_factory):
|
|
|
|
return tmpdir_factory.mktemp('data', numbered=False)
|
|
|
|
def test_some(session_dir):
|
2018-09-20 00:17:10 +08:00
|
|
|
assert session_dir.isdir()
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
|
|
|
)
|
2015-07-29 07:35:13 +08:00
|
|
|
reprec = testdir.inline_run()
|
2015-09-16 23:20:07 +08:00
|
|
|
reprec.assertoutcome(passed=1)
|
|
|
|
|
|
|
|
|
|
|
|
def test_tmpdir_fallback_tox_env(testdir, monkeypatch):
|
|
|
|
"""Test that tmpdir works even if environment variables required by getpass
|
|
|
|
module are missing (#1010).
|
|
|
|
"""
|
2018-05-23 22:48:46 +08:00
|
|
|
monkeypatch.delenv("USER", raising=False)
|
|
|
|
monkeypatch.delenv("USERNAME", raising=False)
|
|
|
|
testdir.makepyfile(
|
|
|
|
"""
|
2015-09-16 23:20:07 +08:00
|
|
|
import pytest
|
|
|
|
def test_some(tmpdir):
|
|
|
|
assert tmpdir.isdir()
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
|
|
|
)
|
2015-09-16 23:20:07 +08:00
|
|
|
reprec = testdir.inline_run()
|
|
|
|
reprec.assertoutcome(passed=1)
|
2015-09-16 23:47:50 +08:00
|
|
|
|
|
|
|
|
2015-09-30 03:00:12 +08:00
|
|
|
@pytest.fixture
|
|
|
|
def break_getuser(monkeypatch):
|
2018-05-23 22:48:46 +08:00
|
|
|
monkeypatch.setattr("os.getuid", lambda: -1)
|
2015-09-30 03:00:12 +08:00
|
|
|
# taken from python 2.7/3.4
|
2018-05-23 22:48:46 +08:00
|
|
|
for envvar in ("LOGNAME", "USER", "LNAME", "USERNAME"):
|
2015-09-30 03:00:12 +08:00
|
|
|
monkeypatch.delenv(envvar, raising=False)
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.usefixtures("break_getuser")
|
2018-05-23 22:48:46 +08:00
|
|
|
@pytest.mark.skipif(sys.platform.startswith("win"), reason="no os.getuid on windows")
|
2015-09-30 03:00:12 +08:00
|
|
|
def test_tmpdir_fallback_uid_not_found(testdir):
|
2015-09-19 09:06:13 +08:00
|
|
|
"""Test that tmpdir works even if the current process's user id does not
|
|
|
|
correspond to a valid user.
|
|
|
|
"""
|
|
|
|
|
2018-05-23 22:48:46 +08:00
|
|
|
testdir.makepyfile(
|
|
|
|
"""
|
2015-09-19 09:06:13 +08:00
|
|
|
import pytest
|
|
|
|
def test_some(tmpdir):
|
|
|
|
assert tmpdir.isdir()
|
2018-05-23 22:48:46 +08:00
|
|
|
"""
|
|
|
|
)
|
2015-09-19 09:06:13 +08:00
|
|
|
reprec = testdir.inline_run()
|
|
|
|
reprec.assertoutcome(passed=1)
|
|
|
|
|
|
|
|
|
2015-09-30 03:00:12 +08:00
|
|
|
@pytest.mark.usefixtures("break_getuser")
|
2018-05-23 22:48:46 +08:00
|
|
|
@pytest.mark.skipif(sys.platform.startswith("win"), reason="no os.getuid on windows")
|
2015-09-30 03:00:12 +08:00
|
|
|
def test_get_user_uid_not_found():
|
2015-09-19 09:06:13 +08:00
|
|
|
"""Test that get_user() function works even if the current process's
|
|
|
|
user id does not correspond to a valid user (e.g. running pytest in a
|
|
|
|
Docker container with 'docker run -u'.
|
|
|
|
"""
|
|
|
|
from _pytest.tmpdir import get_user
|
2018-05-23 22:48:46 +08:00
|
|
|
|
2015-09-19 09:06:13 +08:00
|
|
|
assert get_user() is None
|
|
|
|
|
|
|
|
|
2018-05-23 22:48:46 +08:00
|
|
|
@pytest.mark.skipif(not sys.platform.startswith("win"), reason="win only")
|
2015-09-16 23:47:50 +08:00
|
|
|
def test_get_user(monkeypatch):
|
|
|
|
"""Test that get_user() function works even if environment variables
|
2015-09-17 00:06:39 +08:00
|
|
|
required by getpass module are missing from the environment on Windows
|
|
|
|
(#1010).
|
2015-09-16 23:47:50 +08:00
|
|
|
"""
|
|
|
|
from _pytest.tmpdir import get_user
|
2018-05-23 22:48:46 +08:00
|
|
|
|
|
|
|
monkeypatch.delenv("USER", raising=False)
|
|
|
|
monkeypatch.delenv("USERNAME", raising=False)
|
2015-09-17 03:42:07 +08:00
|
|
|
assert get_user() is None
|
2018-09-20 22:10:33 +08:00
|
|
|
|
|
|
|
|
|
|
|
class TestNumberedDir(object):
|
|
|
|
PREFIX = "fun-"
|
|
|
|
|
|
|
|
def test_make(self, tmp_path):
|
2018-09-29 17:42:31 +08:00
|
|
|
from _pytest.pathlib import make_numbered_dir
|
2018-09-20 22:10:33 +08:00
|
|
|
|
|
|
|
for i in range(10):
|
|
|
|
d = make_numbered_dir(root=tmp_path, prefix=self.PREFIX)
|
|
|
|
assert d.name.startswith(self.PREFIX)
|
|
|
|
assert d.name.endswith(str(i))
|
|
|
|
|
2018-10-18 02:43:27 +08:00
|
|
|
symlink = tmp_path.joinpath(self.PREFIX + "current")
|
2018-10-18 03:39:23 +08:00
|
|
|
if symlink.exists():
|
|
|
|
# unix
|
|
|
|
assert symlink.is_symlink()
|
|
|
|
assert symlink.resolve() == d.resolve()
|
2018-10-18 02:43:27 +08:00
|
|
|
|
2018-09-20 22:10:33 +08:00
|
|
|
def test_cleanup_lock_create(self, tmp_path):
|
|
|
|
d = tmp_path.joinpath("test")
|
|
|
|
d.mkdir()
|
2018-09-29 17:42:31 +08:00
|
|
|
from _pytest.pathlib import create_cleanup_lock
|
2018-09-20 22:10:33 +08:00
|
|
|
|
|
|
|
lockfile = create_cleanup_lock(d)
|
|
|
|
with pytest.raises(EnvironmentError, match="cannot create lockfile in .*"):
|
|
|
|
create_cleanup_lock(d)
|
|
|
|
|
|
|
|
lockfile.unlink()
|
|
|
|
|
|
|
|
def test_lock_register_cleanup_removal(self, tmp_path):
|
2018-09-29 17:42:31 +08:00
|
|
|
from _pytest.pathlib import create_cleanup_lock, register_cleanup_lock_removal
|
2018-09-20 22:10:33 +08:00
|
|
|
|
|
|
|
lock = create_cleanup_lock(tmp_path)
|
|
|
|
|
|
|
|
registry = []
|
|
|
|
register_cleanup_lock_removal(lock, register=registry.append)
|
|
|
|
|
|
|
|
cleanup_func, = registry
|
|
|
|
|
|
|
|
assert lock.is_file()
|
|
|
|
|
|
|
|
cleanup_func(original_pid="intentionally_different")
|
|
|
|
|
|
|
|
assert lock.is_file()
|
|
|
|
|
|
|
|
cleanup_func()
|
|
|
|
|
|
|
|
assert not lock.exists()
|
|
|
|
|
|
|
|
cleanup_func()
|
|
|
|
|
|
|
|
assert not lock.exists()
|
|
|
|
|
2018-10-15 03:20:34 +08:00
|
|
|
def _do_cleanup(self, tmp_path):
|
2018-09-20 22:10:33 +08:00
|
|
|
self.test_make(tmp_path)
|
2018-09-29 17:42:31 +08:00
|
|
|
from _pytest.pathlib import cleanup_numbered_dir
|
2018-09-20 22:10:33 +08:00
|
|
|
|
|
|
|
cleanup_numbered_dir(
|
2018-09-29 04:06:43 +08:00
|
|
|
root=tmp_path,
|
|
|
|
prefix=self.PREFIX,
|
|
|
|
keep=2,
|
|
|
|
consider_lock_dead_if_created_before=0,
|
2018-09-20 22:10:33 +08:00
|
|
|
)
|
2018-10-15 03:20:34 +08:00
|
|
|
|
|
|
|
def test_cleanup_keep(self, tmp_path):
|
|
|
|
self._do_cleanup(tmp_path)
|
2018-10-18 03:16:44 +08:00
|
|
|
a, b = (x for x in tmp_path.iterdir() if not x.is_symlink())
|
2018-09-20 22:10:33 +08:00
|
|
|
print(a, b)
|
2018-09-27 02:41:33 +08:00
|
|
|
|
|
|
|
def test_cleanup_locked(self, tmp_path):
|
|
|
|
|
2018-09-29 17:42:31 +08:00
|
|
|
from _pytest import pathlib
|
2018-09-27 02:41:33 +08:00
|
|
|
|
2018-09-29 17:42:31 +08:00
|
|
|
p = pathlib.make_numbered_dir(root=tmp_path, prefix=self.PREFIX)
|
2018-09-27 02:41:33 +08:00
|
|
|
|
2018-09-29 17:42:31 +08:00
|
|
|
pathlib.create_cleanup_lock(p)
|
2018-09-29 04:06:43 +08:00
|
|
|
|
2018-09-29 17:42:31 +08:00
|
|
|
assert not pathlib.ensure_deletable(
|
2018-09-29 04:06:43 +08:00
|
|
|
p, consider_lock_dead_if_created_before=p.stat().st_mtime - 1
|
|
|
|
)
|
2018-09-29 17:42:31 +08:00
|
|
|
assert pathlib.ensure_deletable(
|
2018-09-29 04:06:43 +08:00
|
|
|
p, consider_lock_dead_if_created_before=p.stat().st_mtime + 1
|
|
|
|
)
|
2018-10-01 22:39:24 +08:00
|
|
|
|
|
|
|
def test_rmtree(self, tmp_path):
|
|
|
|
from _pytest.pathlib import rmtree
|
|
|
|
|
|
|
|
adir = tmp_path / "adir"
|
|
|
|
adir.mkdir()
|
|
|
|
rmtree(adir)
|
|
|
|
|
|
|
|
assert not adir.exists()
|
|
|
|
|
|
|
|
adir.mkdir()
|
|
|
|
afile = adir / "afile"
|
|
|
|
afile.write_bytes(b"aa")
|
|
|
|
|
|
|
|
rmtree(adir, force=True)
|
|
|
|
assert not adir.exists()
|
2018-10-15 03:20:34 +08:00
|
|
|
|
2018-10-24 13:45:53 +08:00
|
|
|
def test_cleanup_ignores_symlink(self, tmp_path):
|
2018-10-15 03:20:34 +08:00
|
|
|
the_symlink = tmp_path / (self.PREFIX + "current")
|
2018-10-15 05:21:04 +08:00
|
|
|
attempt_symlink_to(the_symlink, tmp_path / (self.PREFIX + "5"))
|
2018-10-15 03:20:34 +08:00
|
|
|
self._do_cleanup(tmp_path)
|
2018-10-15 05:21:04 +08:00
|
|
|
|
2018-10-24 13:45:53 +08:00
|
|
|
def test_removal_accepts_lock(self, tmp_path):
|
|
|
|
folder = pathlib.make_numbered_dir(root=tmp_path, prefix=self.PREFIX)
|
|
|
|
pathlib.create_cleanup_lock(folder)
|
|
|
|
pathlib.maybe_delete_a_numbered_dir(folder)
|
|
|
|
assert folder.is_dir()
|
|
|
|
|
2018-10-15 05:21:04 +08:00
|
|
|
|
|
|
|
def attempt_symlink_to(path, to_path):
|
|
|
|
"""Try to make a symlink from "path" to "to_path", skipping in case this platform
|
|
|
|
does not support it or we don't have sufficient privileges (common on Windows)."""
|
|
|
|
if sys.platform.startswith("win") and six.PY2:
|
|
|
|
pytest.skip("pathlib for some reason cannot make symlinks on Python 2")
|
|
|
|
try:
|
|
|
|
Path(path).symlink_to(Path(to_path))
|
|
|
|
except OSError:
|
|
|
|
pytest.skip("could not create symbolic link")
|
2019-01-27 20:05:34 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_tmpdir_equals_tmp_path(tmpdir, tmp_path):
|
|
|
|
assert Path(tmpdir) == tmp_path
|