From 4b7c02775e38c6a9f8969dee1f4e35a02561c25a Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Fri, 16 Oct 2015 00:12:02 +0200 Subject: [PATCH 1/5] benchmarks: test with both the binary and the python code we use forking mode always and either execute python with the archiver module or the "borg.exe" binary. the cmd fixture alternates between 'python' and 'binary' mode and calls exec_cmd accordingly. --- borg/testsuite/archiver.py | 9 +++++++-- borg/testsuite/benchmark.py | 15 +++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/borg/testsuite/archiver.py b/borg/testsuite/archiver.py index 00a3a2bd9..81906bf27 100644 --- a/borg/testsuite/archiver.py +++ b/borg/testsuite/archiver.py @@ -71,10 +71,15 @@ class environment_variable: os.environ[k] = v -def exec_cmd(*args, archiver=None, fork=False, **kw): +def exec_cmd(*args, archiver=None, fork=False, exe=None, **kw): if fork: try: - borg = (sys.executable, '-m', 'borg.archiver') + if exe is None: + borg = (sys.executable, '-m', 'borg.archiver') + elif isinstance(exe, str): + borg = (exe, ) + elif not isinstance(exe, tuple): + raise ValueError('exe must be None, a tuple or a str') output = subprocess.check_output(borg + args) ret = 0 except subprocess.CalledProcessError as e: diff --git a/borg/testsuite/benchmark.py b/borg/testsuite/benchmark.py index 5b5c38634..d7bf95bb0 100644 --- a/borg/testsuite/benchmark.py +++ b/borg/testsuite/benchmark.py @@ -13,10 +13,17 @@ import pytest from .archiver import changedir, exec_cmd -# TODO: use fixture params to test python code and binary -@pytest.fixture -def cmd(): - return exec_cmd +@pytest.fixture(params=['python', 'binary']) +def cmd(request): + if request.param == 'python': + exe = None + elif request.param == 'binary': + exe = 'borg.exe' + else: + raise ValueError("param must be 'python' or 'binary'") + def exec_fn(*args, **kw): + return exec_cmd(*args, exe=exe, fork=True, **kw) + return exec_fn @pytest.yield_fixture From 1a248116dbaaef3a470815e67bcb332315cdd664 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Fri, 16 Oct 2015 00:18:46 +0200 Subject: [PATCH 2/5] move cmd fixture to archiver test module --- borg/testsuite/archiver.py | 13 +++++++++++++ borg/testsuite/benchmark.py | 15 +-------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/borg/testsuite/archiver.py b/borg/testsuite/archiver.py index 81906bf27..c92775ec6 100644 --- a/borg/testsuite/archiver.py +++ b/borg/testsuite/archiver.py @@ -71,6 +71,19 @@ class environment_variable: os.environ[k] = v +@pytest.fixture(params=['python', 'binary']) +def cmd(request): + if request.param == 'python': + exe = None + elif request.param == 'binary': + exe = 'borg.exe' + else: + raise ValueError("param must be 'python' or 'binary'") + def exec_fn(*args, **kw): + return exec_cmd(*args, exe=exe, fork=True, **kw) + return exec_fn + + def exec_cmd(*args, archiver=None, fork=False, exe=None, **kw): if fork: try: diff --git a/borg/testsuite/benchmark.py b/borg/testsuite/benchmark.py index d7bf95bb0..e7d9b2487 100644 --- a/borg/testsuite/benchmark.py +++ b/borg/testsuite/benchmark.py @@ -10,20 +10,7 @@ import os import pytest -from .archiver import changedir, exec_cmd - - -@pytest.fixture(params=['python', 'binary']) -def cmd(request): - if request.param == 'python': - exe = None - elif request.param == 'binary': - exe = 'borg.exe' - else: - raise ValueError("param must be 'python' or 'binary'") - def exec_fn(*args, **kw): - return exec_cmd(*args, exe=exe, fork=True, **kw) - return exec_fn +from .archiver import changedir, cmd @pytest.yield_fixture From 9b10e8a3f3d48e2acc6be10cd7e2cf8dd07ca15d Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Fri, 16 Oct 2015 00:52:23 +0200 Subject: [PATCH 3/5] if borg.exe is not present, do not try to test it --- borg/testsuite/archiver.py | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/borg/testsuite/archiver.py b/borg/testsuite/archiver.py index c92775ec6..cecc6016c 100644 --- a/borg/testsuite/archiver.py +++ b/borg/testsuite/archiver.py @@ -1,5 +1,6 @@ from binascii import hexlify from configparser import RawConfigParser +import errno import os from io import StringIO import stat @@ -70,20 +71,6 @@ class environment_variable: else: os.environ[k] = v - -@pytest.fixture(params=['python', 'binary']) -def cmd(request): - if request.param == 'python': - exe = None - elif request.param == 'binary': - exe = 'borg.exe' - else: - raise ValueError("param must be 'python' or 'binary'") - def exec_fn(*args, **kw): - return exec_cmd(*args, exe=exe, fork=True, **kw) - return exec_fn - - def exec_cmd(*args, archiver=None, fork=False, exe=None, **kw): if fork: try: @@ -112,6 +99,29 @@ def exec_cmd(*args, archiver=None, fork=False, exe=None, **kw): sys.stdin, sys.stdout, sys.stderr = stdin, stdout, stderr +# check if the binary "borg.exe" is available +try: + exec_cmd('help', exe='borg.exe', fork=True) + BORG_EXES = ['python', 'binary', ] +except IOError as err: + if err.errno != errno.ENOENT: + raise + BORG_EXES = ['python', ] + + +@pytest.fixture(params=BORG_EXES) +def cmd(request): + if request.param == 'python': + exe = None + elif request.param == 'binary': + exe = 'borg.exe' + else: + raise ValueError("param must be 'python' or 'binary'") + def exec_fn(*args, **kw): + return exec_cmd(*args, exe=exe, fork=True, **kw) + return exec_fn + + class ArchiverTestCaseBase(BaseTestCase): prefix = '' From 60cdb5f716f9437de45a8159127d77fb66507802 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sun, 18 Oct 2015 18:48:36 +0200 Subject: [PATCH 4/5] make archiver tests run for the python source as well as for the pyinstaller binary, fixes #215 if the borg.exe binary is not available in PATH, binary tests are skipped. source tests are run without forking (for better speed, esp. on travis). binary tests need forking the binary, of course. for source tests, some tests check for an exception to happen. for a forked binary, we of course can only check the exit code, which is non-zero in that case. --- borg/testsuite/archiver.py | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/borg/testsuite/archiver.py b/borg/testsuite/archiver.py index cecc6016c..2f4723331 100644 --- a/borg/testsuite/archiver.py +++ b/borg/testsuite/archiver.py @@ -123,12 +123,13 @@ def cmd(request): class ArchiverTestCaseBase(BaseTestCase): - + EXE = None # python source based + FORK_DEFAULT = False prefix = '' def setUp(self): os.environ['BORG_CHECK_I_KNOW_WHAT_I_AM_DOING'] = '1' - self.archiver = Archiver() + self.archiver = not self.FORK_DEFAULT and Archiver() or None self.tmpdir = tempfile.mkdtemp() self.repository_path = os.path.join(self.tmpdir, 'repository') self.repository_location = self.prefix + self.repository_path @@ -154,7 +155,10 @@ class ArchiverTestCaseBase(BaseTestCase): def cmd(self, *args, **kw): exit_code = kw.pop('exit_code', 0) - ret, output = exec_cmd(*args, archiver=self.archiver, **kw) + fork = kw.pop('fork', None) + if fork is None: + fork = self.FORK_DEFAULT + ret, output = exec_cmd(*args, fork=fork, exe=self.EXE, archiver=self.archiver, **kw) if ret != exit_code: print(output) self.assert_equal(ret, exit_code) @@ -333,7 +337,10 @@ class ArchiverTestCase(ArchiverTestCaseBase): self.cmd('init', '--encryption=none', self.repository_location) self._set_repository_id(self.repository_path, repository_id) self.assert_equal(repository_id, self._extract_repository_id(self.repository_path)) - self.assert_raises(Cache.EncryptionMethodMismatch, lambda: self.cmd('create', self.repository_location + '::test.2', 'input')) + if self.FORK_DEFAULT: + self.cmd('create', self.repository_location + '::test.2', 'input', exit_code=1) # fails + else: + self.assert_raises(Cache.EncryptionMethodMismatch, lambda: self.cmd('create', self.repository_location + '::test.2', 'input')) def test_repository_swap_detection2(self): self.create_test_files() @@ -343,7 +350,10 @@ class ArchiverTestCase(ArchiverTestCaseBase): self.cmd('create', self.repository_location + '_encrypted::test', 'input') shutil.rmtree(self.repository_path + '_encrypted') os.rename(self.repository_path + '_unencrypted', self.repository_path + '_encrypted') - self.assert_raises(Cache.RepositoryAccessAborted, lambda: self.cmd('create', self.repository_location + '_encrypted::test.2', 'input')) + if self.FORK_DEFAULT: + self.cmd('create', self.repository_location + '_encrypted::test.2', 'input', exit_code=1) # fails + else: + self.assert_raises(Cache.RepositoryAccessAborted, lambda: self.cmd('create', self.repository_location + '_encrypted::test.2', 'input')) def test_strip_components(self): self.cmd('init', self.repository_location) @@ -568,8 +578,12 @@ class ArchiverTestCase(ArchiverTestCaseBase): self.assert_in('bar-2015-08-12-20:00', output) def test_usage(self): - self.assert_raises(SystemExit, lambda: self.cmd()) - self.assert_raises(SystemExit, lambda: self.cmd('-h')) + if self.FORK_DEFAULT: + self.cmd(exit_code=0) + self.cmd('-h', exit_code=0) + else: + self.assert_raises(SystemExit, lambda: self.cmd()) + self.assert_raises(SystemExit, lambda: self.cmd('-h')) def test_help(self): assert 'Borg' in self.cmd('help') @@ -656,6 +670,12 @@ class ArchiverTestCase(ArchiverTestCaseBase): self.verify_aes_counter_uniqueness('passphrase') +@unittest.skipUnless('binary' in BORG_EXES, 'no borg.exe available') +class ArchiverTestCaseBinary(ArchiverTestCase): + EXE = 'borg.exe' + FORK_DEFAULT = True + + class ArchiverCheckTestCase(ArchiverTestCaseBase): def setUp(self): From 723590df3d269d27cc55035a8c1b92a9fcd947cb Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sun, 18 Oct 2015 19:18:24 +0200 Subject: [PATCH 5/5] fix borg.exe presence detection for python3.2 --- borg/testsuite/archiver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/borg/testsuite/archiver.py b/borg/testsuite/archiver.py index 2f4723331..f2de2282c 100644 --- a/borg/testsuite/archiver.py +++ b/borg/testsuite/archiver.py @@ -103,7 +103,7 @@ def exec_cmd(*args, archiver=None, fork=False, exe=None, **kw): try: exec_cmd('help', exe='borg.exe', fork=True) BORG_EXES = ['python', 'binary', ] -except IOError as err: +except (IOError, OSError) as err: if err.errno != errno.ENOENT: raise BORG_EXES = ['python', ]