Пример #1
0
def test_handling_of_nonexisting_path(with_callback, existing_torrents):
    # Create and prepare existing torrents
    existing_torrents = existing_torrents(my_torrents=(
        ('a', 'foo', {
            'creation_date': 123
        }),
        ('b', 'bar', {
            'creation_date': 456
        }),
        ('c', 'baz', {
            'creation_date': 789
        }),
    ), )

    # Create and prepare the torrent we want to generate
    new_content = existing_torrents.my_torrents[0]
    new_torrent = torf.Torrent(path=new_content.content_path)

    # Expect identical metainfo
    exp_joined_metainfo = copy.deepcopy(new_torrent.metainfo)

    # Reuse existing torrent
    reuse_torrent_path = 'path/to/nonexisting/directory'
    if with_callback:
        callback = Mock(return_value=None)
        return_value = new_torrent.reuse(reuse_torrent_path, callback=callback)

        # Confirm everything happened as expected
        assert return_value is False
        assert new_torrent.metainfo == exp_joined_metainfo
        assert callback.call_args_list == [
            call(
                new_torrent,
                None,
                0,
                0,
                False,
                ComparableException(
                    torf.ReadError(errno.ENOENT, reuse_torrent_path), ),
            ),
        ]

    else:
        exp_exception = torf.ReadError(errno.ENOENT, reuse_torrent_path)
        with pytest.raises(type(exp_exception),
                           match=rf'^{re.escape(str(exp_exception))}$'):
            new_torrent.reuse(reuse_torrent_path)
        assert new_torrent.metainfo == exp_joined_metainfo
Пример #2
0
 def exp_exc_files_missing(self):
     if not hasattr(self, '_exp_exc_files_missing'):
         self._exp_exc_files_missing = fuzzylist(
             *(ComparableException(torf.ReadError(errno.ENOENT, filepath))
               for filepath in self.files_missing))
         debug(f'Expected files missing: {self._exp_exc_files_missing}')
     return self._exp_exc_files_missing
Пример #3
0
def test_ReadError():
    for cls,args,kwargs in ((err.ReadError, ('path/to/file: No such file or directory',), {}),
                            (err.Error, (torf.ReadError(errno.ENOENT, 'path/to/file'),), {}),
                            (err.Error, (torf.PathError('path/to/file', msg='No such file or directory'),), {}),
                            (err.Error, ('path/to/file: No such file or directory', err.Code.READ), {}),
                            (err.Error, ('path/to/file: No such file or directory',), {'code': err.Code.READ})):
        with pytest.raises(err.ReadError) as exc_info:
            raise cls(*args, **kwargs)
        assert exc_info.value.exit_code is err.Code.READ
        assert str(exc_info.value) == 'path/to/file: No such file or directory'
Пример #4
0
def test_callback_cancels_when_handling(cancel_condition,
                                        exp_callback_calls_count,
                                        existing_torrents, create_file):
    # Create and prepare existing torrents
    existing_torrents = existing_torrents(
        readable1=(
            ('a', 'foo', {
                'creation_date': 123
            }),
            ('b', 'bar', {
                'creation_date': 456
            }),
            ('c', 'baz', {
                'creation_date': 789
            }),
        ),
        # Unreadable directory
        unreadable=(),
        readable2=(
            ('d', 'hey', {
                'private': True
            }),
            ('e', 'ho', {
                'comment': 'yo'
            }),
            ('f', 'oh', {
                'comment': 'oy'
            }),
            ('g', 'ohh', {
                'comment': 'oyy'
            }),
            ('h', 'ohy', {
                'comment': 'hoyo'
            }),
        ),
    )
    # ReadError (directory)
    existing_torrents.locations['unreadable'].chmod(0o300)
    # ReadError (torrent file)
    existing_torrents.readable2[1].torrent_path.chmod(0o300)
    # BdecodeError
    data = bytearray(existing_torrents.readable2[2].torrent_path.read_bytes())
    data[0] = ord('x')
    existing_torrents.readable2[2].torrent_path.write_bytes(data)
    # MetainfoError
    del existing_torrents.readable2[3].torrent.metainfo['info']['piece length']
    existing_torrents.readable2[3].torrent.write(
        existing_torrents.readable2[3].torrent_path,
        validate=False,
        overwrite=True,
    )

    # Create and prepare the torrent we want to generate
    new_content = existing_torrents.readable2[4].content_path
    new_torrent = torf.Torrent(path=new_content)
    exp_joined_metainfo = copy.deepcopy(new_torrent.metainfo)

    def callback(torrent, torrent_path, done, total, is_match, exception):
        if cancel_condition(torrent_path, is_match):
            return 'cancel'

    callback_wrapper = Mock(side_effect=callback)

    # Reuse existing torrent
    return_value = new_torrent.reuse(existing_torrents.location_paths,
                                     callback=callback_wrapper)

    # Confirm everything happened as expected
    assert return_value is False
    assert new_torrent.metainfo == exp_joined_metainfo

    all_callback_calls = [
        call(new_torrent, str(existing_torrents.readable1[0].torrent_path), 1,
             8, False, None),
        call(new_torrent, str(existing_torrents.readable1[1].torrent_path), 2,
             8, False, None),
        call(new_torrent, str(existing_torrents.readable1[2].torrent_path), 3,
             8, False, None),
        call(
            new_torrent,
            None,
            3,
            8,
            False,
            ComparableException(
                torf.ReadError(
                    errno.EACCES,
                    str(existing_torrents.locations['unreadable'])), ),
        ),
        call(new_torrent, str(existing_torrents.readable2[0].torrent_path), 4,
             8, False, None),
        call(
            new_torrent,
            str(existing_torrents.readable2[1].torrent_path),
            5,
            8,
            False,
            ComparableException(
                torf.ReadError(
                    errno.EACCES,
                    str(existing_torrents.readable2[1].torrent_path)), ),
        ),
        call(
            new_torrent,
            str(existing_torrents.readable2[2].torrent_path),
            6,
            8,
            False,
            ComparableException(
                torf.BdecodeError(
                    str(existing_torrents.readable2[2].torrent_path)), ),
        ),
        call(
            new_torrent,
            str(existing_torrents.readable2[3].torrent_path),
            7,
            8,
            False,
            ComparableException(
                torf.MetainfoError("Missing 'piece length' in ['info']"), ),
        ),
        call(new_torrent, str(existing_torrents.readable2[4].torrent_path), 8,
             8, None, None),
        call(new_torrent, str(existing_torrents.readable2[4].torrent_path), 8,
             8, False, None),
    ]
    assert callback_wrapper.call_args_list == all_callback_calls[:
                                                                 exp_callback_calls_count]
Пример #5
0
def test_exceptions(with_callback, existing_torrents):
    # Create and prepare existing torrents
    existing_torrents = existing_torrents(
        readable1=(
            ('a', 'foo', {
                'creation_date': 123
            }),
            ('b', 'bar', {
                'creation_date': 456
            }),
            ('c', 'baz', {
                'creation_date': 789
            }),
        ),
        unreadable=(),
        readable2=(
            ('d', 'hey', {
                'private': True
            }),
            ('e', 'ho', {
                'comment': 'yo'
            }),
            ('f', 'oh', {
                'comment': 'oy'
            }),
            ('g', 'ohh', {
                'comment': 'oyy'
            }),
        ),
    )
    # Unreadable directory
    existing_torrents.locations['unreadable'].chmod(0o300)
    # Unreadable torrent file
    existing_torrents.readable2[1].torrent_path.chmod(0o300)
    # Nonexisting torrent file
    nonexisting_torrent_file = 'no/such/path.torrent'

    # Create and prepare the torrent we want to generate
    new_content = existing_torrents.readable2[2]
    new_torrent = torf.Torrent(
        path=new_content.content_path,
        trackers=('http://foo:1000', 'http://foo:2000'),
        webseeds=('http://bar:1000', ),
        httpseeds=('http://baz:1000', ),
        private=True,
        comment='This is a custom torrent',
        creation_date=123000,
        created_by='CREATOR',
        source='SRC',
        piece_size=8 * 1048576,
        randomize_infohash=True,
    )

    # Reuse existing torrent
    if with_callback:
        # Expect the same metainfo, but with important parts copied
        exp_joined_metainfo = copy.deepcopy(new_torrent.metainfo)
        exp_joined_metainfo['info'][
            'piece length'] = new_content.torrent.metainfo['info'][
                'piece length']
        exp_joined_metainfo['info']['pieces'] = new_content.torrent.metainfo[
            'info']['pieces']

        callback = Mock(return_value=None)
        location_paths = (
            nonexisting_torrent_file, ) + existing_torrents.location_paths
        return_value = new_torrent.reuse(location_paths, callback=callback)

        # Confirm everything happened as expected
        assert return_value is True
        assert new_torrent.metainfo == exp_joined_metainfo
        for c in callback.call_args_list:
            print(c)

        assert callback.call_args_list == [
            call(
                new_torrent,
                nonexisting_torrent_file,
                1,
                8,
                False,
                ComparableException(
                    torf.ReadError(errno.ENOENT, nonexisting_torrent_file), ),
            ),
            call(new_torrent, str(existing_torrents.readable1[0].torrent_path),
                 2, 8, False, None),
            call(new_torrent, str(existing_torrents.readable1[1].torrent_path),
                 3, 8, False, None),
            call(new_torrent, str(existing_torrents.readable1[2].torrent_path),
                 4, 8, False, None),
            call(
                new_torrent,
                None,
                4,
                8,
                False,
                ComparableException(
                    torf.ReadError(
                        errno.EACCES,
                        str(existing_torrents.locations['unreadable'])), ),
            ),
            call(new_torrent, str(existing_torrents.readable2[0].torrent_path),
                 5, 8, False, None),
            call(
                new_torrent,
                str(existing_torrents.readable2[1].torrent_path),
                6,
                8,
                False,
                ComparableException(
                    torf.ReadError(
                        errno.EACCES,
                        str(existing_torrents.readable2[1].torrent_path)), ),
            ),
            call(new_torrent, str(existing_torrents.readable2[2].torrent_path),
                 7, 8, None, None),
            call(new_torrent, str(existing_torrents.readable2[2].torrent_path),
                 7, 8, True, None),
        ]
    else:
        # Expect identical metainfo
        exp_joined_metainfo = copy.deepcopy(new_torrent.metainfo)

        exp_exception = torf.ReadError(
            errno.EACCES, str(existing_torrents.locations['unreadable']))
        with pytest.raises(type(exp_exception),
                           match=rf'^{re.escape(str(exp_exception))}$'):
            new_torrent.reuse(existing_torrents.location_paths)

        # Confirm everything happened as expected
        assert new_torrent.metainfo == exp_joined_metainfo