Comment 0 for bug 1833685

Revision history for this message
Sebastien Bacher (seb128) wrote : [0.8] VerifyTest fails with AttributeError

Using 0.8 r1377

$ cd /tmp
$ bzr branch lp:duplicity
$ cd duplicity
$ python2.3 setup.py build --force
$ PYTHONPATH=/tmp/duplicity/build/lib.linux-i686-3.7/ python3.7 ./setup.py test
(that's on an i386 chroot, path to adapt for amd64)

The tests have some errors, including that one

___________ VerifyTest.test_verify_compare_data_changed_source_file ____________

self = <testing.functional.test_verify.VerifyTest testMethod=test_verify_compare_data_changed_source_file>

    def test_verify_compare_data_changed_source_file(self):
        u"""Test verify with --compare-data gives an error if a source file is changed"""
> self.backup(u"full", u"testfiles/various_file_types", options=[])

functional/test_verify.py:83:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
functional/__init__.py:182: in backup
    result = self.run_duplicity(options=options, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <testing.functional.test_verify.VerifyTest testMethod=test_verify_compare_data_changed_source_file>
options = ['full', 'testfiles/various_file_types', 'file://testfiles/output', '--volsize', '1']
current_time = None, fail = None, passphrase_input = []

    def run_duplicity(self, options=[], current_time=None, fail=None,
                      passphrase_input=[]):
        u"""
        Run duplicity binary with given arguments and options
        """
        # We run under setsid and take input from /dev/null (below) because
        # this way we force a failure if duplicity tries to read from the
        # console unexpectedly (like for gpg password or such).

        # Check all string inputs are unicode -- we will convert to system encoding before running the command
        for item in options:
            if sys.version_info.major == 2:
                assert not isinstance(item, str), u"item " + unicode(item) + u" in options is not unicode"

        for item in passphrase_input:
            assert isinstance(item, u"".__class__), u"item " + unicode(item) + u" in passphrase_input is not unicode"

        if platform.platform().startswith(u'Linux'):
            cmd_list = [u'setsid']
            if self._setsid_w:
                cmd_list.extend([u"-w"])
        else:
            cmd_list = []
        cmd_list.extend([u"../bin/duplicity"])
        cmd_list.extend(options)
        cmd_list.extend([u"-v0"])
        cmd_list.extend([u"--no-print-statistics"])
        cmd_list.extend([u"--allow-source-mismatch"])
        cmd_list.extend([u"--archive-dir=testfiles/cache"])
        if current_time:
            cmd_list.extend([u"--current-time", current_time])
        cmd_list.extend(self.class_args)
        if fail:
            cmd_list.extend([u"--fail", u"".__class__(fail)])
        cmdline = u" ".join([u'"%s"' % x for x in cmd_list])

        if not passphrase_input:
            cmdline += u" < /dev/null"

        # The immediately following block is the nicer way to execute pexpect with
        # unicode strings, but we need to have the pre-4.0 version for some time yet,
        # so for now this is commented out so tests execute the same way on all systems.

        # if parse_version(pexpect.__version__) >= parse_version("4.0"):
        # # pexpect.spawn only supports unicode from version 4.0
        # # there was a separate pexpect.spawnu in 3.x, but it has an error on readline
        # child = pexpect.spawn(u'/bin/sh', [u'-c', cmdline], timeout=None, encoding=sys.getfilesystemencoding())
        #
        # for passphrase in passphrase_input:
        # child.expect(u'passphrase.*:')
        # child.sendline(passphrase)
        # else:

        # Manually encode to filesystem encoding and send to spawn as bytes
        # ToDo: Remove this once we no longer have to support systems with pexpect < 4.0
        if sys.version_info.major > 2:
            child = pexpect.spawn(u'/bin/sh', [u'-c', cmdline], timeout=None)
        else:
            child = pexpect.spawn(b'/bin/sh', [b'-c', cmdline.encode(sys.getfilesystemencoding(),
                                                                 u'replace')], timeout=None)

        for passphrase in passphrase_input:
            child.expect(b'passphrase.*:')
            child.sendline(passphrase)

        # if the command fails, we need to clear its output
        # so it will terminate cleanly.
        child.expect_exact(pexpect.EOF)
        lines = child.before.splitlines()
        child.wait()
        child.ptyproc.delayafterclose = 0.0
        return_val = child.exitstatus

        if fail:
            self.assertEqual(30, return_val)
        elif return_val:
            print(u"\n...command:", cmdline, file=sys.stderr)
            print(u"...cwd:", os.getcwd(), file=sys.stderr)
            print(u"...output:", file=sys.stderr)
            for line in lines:
                line = line.rstrip()
                if line:
                    print(line, file=sys.stderr)
            print(u"...return_val:", return_val, file=sys.stderr)
> raise CmdError(return_val)
E testing.functional.CmdError: 30

functional/__init__.py:165: CmdError
----------------------------- Captured stderr call -----------------------------

...command: "setsid" "-w" "../bin/duplicity" "full" "testfiles/various_file_types" "file://testfiles/output" "--volsize" "1" "-v0" "--no-print-statistics" "--allow-source-mismatch" "--archive-dir=testfiles/cache" < /dev/null
...cwd: /build/duplicity/testing
...output:
b'Traceback (innermost last):'
b' File "../bin/duplicity", line 1706, in <module>'
b' with_tempdir(main)'
b' File "../bin/duplicity", line 1692, in with_tempdir'
b' fn()'
b' File "../bin/duplicity", line 1538, in main'
b' do_backup(action)'
b' File "../bin/duplicity", line 1662, in do_backup'
b' full_backup(col_stats)'
b' File "../bin/duplicity", line 568, in full_backup'
b' globals.backend)'
b' File "../bin/duplicity", line 425, in write_multivol'
b' globals.volsize)'
b' File "/build/duplicity/duplicity/gpg.py", line 393, in GPGWriteFile'
b' data = block_iter.__next__().data'
b' File "/build/duplicity/duplicity/diffdir.py", line 543, in __next__'
b' result = self.process(next(self.input_iter)) # pylint: disable=assignment-from-no-return'
b' File "/build/duplicity/duplicity/diffdir.py", line 235, in get_delta_iter'
b' (new_path, sig_path, sigTarFile))'
b' File "/build/duplicity/duplicity/robust.py", line 41, in check_common_error'
b' return function(*args)'
b' File "/build/duplicity/duplicity/diffdir.py", line 160, in get_delta_path'
b' sigTarFile.addfile(ti)'
b' File "/usr/lib/python3.7/tarfile.py", line 1966, in addfile'
b' buf = tarinfo.tobuf(self.format, self.encoding, self.errors)'
b' File "/usr/lib/python3.7/tarfile.py", line 816, in tobuf'
b' return self.create_gnu_header(info, encoding, errors)'
b' File "/usr/lib/python3.7/tarfile.py", line 847, in create_gnu_header'
b' return buf + self._create_header(info, GNU_FORMAT, encoding, errors)'
b' File "/usr/lib/python3.7/tarfile.py", line 937, in _create_header'
b' stn(info.get("gname", ""), 32, encoding, errors),'
b' File "/usr/lib/python3.7/tarfile.py", line 161, in stn'
b' s = s.encode(encoding, errors)'
b" AttributeError: 'bytes' object has no attribute 'encode'"
...return_val: 30