TestParseListingLines   A
last analyzed

Complexity

Total Complexity 2

Size/Duplication

Total Lines 16
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 16
rs 10
wmc 2

2 Methods

Rating   Name   Duplication   Size   Complexity  
A test_parse_directory() 0 7 1
A test_parse_file() 0 7 1
1
import io
0 ignored issues
show
Coding Style introduced by
This module should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
2
import os
3
import tempfile
4
import unittest
5
from unittest import mock
6
from urllib.parse import urljoin
7
8
from foil.ftp import (parse_line, ftp_walk, ftp_listing_paths, ListingType,
9
                      FTP_URL_TEMPLATE, download_ftp_url)
10
11
12
FILE_CONTENT = b'mock_content'
13
14
MOCK_FTP_CONFIG = {
15
    'user': 'fake_user',
16
    'password': 'fake_password',
17
    'host': 'host',
18
    'port': 21
19
}
20
21
22
def mock_directory_line(name):
23
    return 'drwxr-xr-x 4   ftsclient       ftsclient 60      Dec 11 10:03 {}'.format(name)
24
25
26
def mock_file_line(name):
27
    return '-rw-r--r-- 1   bd_mgr          online  3661980 Mar 30 02:13 {}'.format(name)
28
29
30
def mock_ftp_walk():
31
    return iter([('/root', ['directory1', 'directory2'], ['file1']),
32
                 ('/root/directory1', ['subdirectory'], []),
33
                 ('/root/directory1/subdirectory', [], ['file1', 'file2']),
34
                 ('/root/directory2', [], [])])
35
36
37
class MockFTPConnection:
0 ignored issues
show
Coding Style introduced by
This class should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
38
    FTP_DIR_TREE = {
39
        '/root': [mock_directory_line('directory1'),
40
                  mock_directory_line('directory2'),
41
                  mock_file_line('file1')],
42
        '/root/directory1': [mock_directory_line('subdirectory')],
43
        '/root/directory1/subdirectory': [mock_file_line('file1'),
44
                                          mock_file_line('file2')],
45
        '/root/directory2': ['totals']}
46
47
    BINARY_DATA = {'file1': b'abc', 'file2': b'123'}
48
49
    def dir(self, path, callback):
50
        listings = self.FTP_DIR_TREE[path]
51
        for listing in listings:
52
            callback(listing)
53
54
    def retrbinary(self, path, callback):
55
        file = path.rpartition(' ')[-1]
56
        callback(self.BINARY_DATA[file])
57
58
59
def mock_url_open(url):
0 ignored issues
show
Unused Code introduced by
The argument url seems to be unused.
Loading history...
60
    return io.BytesIO(FILE_CONTENT)
61
62
63
class TestListingTraversal(unittest.TestCase):
64
    def setUp(self):
65
        self.conn = MockFTPConnection()
66
        self.root = '/root'
67
68
    def test_ftp_walk(self):
69
        expected = list(mock_ftp_walk())
70
        result = list(ftp_walk(self.conn, rootpath=self.root))
71
72
        self.assertEqual(expected, result)
73
74
    def test_ftp_listing_paths(self):
75
        expected = set(['/root/file1',
76
                        '/root/directory1/subdirectory/file1',
77
                        '/root/directory1/subdirectory/file2'])
78
        result = set(ftp_listing_paths(self.conn, self.root))
79
80
        self.assertEqual(expected, result)
81
82
83
class TestParseListingLines(unittest.TestCase):
84
    def test_parse_directory(self):
85
        directory_name = 'photos'
86
        entry = mock_directory_line(directory_name)
87
88
        expected = (ListingType.directory, directory_name)
89
        result = parse_line(entry)
90
        self.assertEqual(expected, result)
91
92
    def test_parse_file(self):
93
        filename = 'katies_photo_album.zip'
94
        entry = mock_file_line(filename)
95
96
        expected = (ListingType.file, filename)
97
        result = parse_line(entry)
98
        self.assertEqual(expected, result)
99
100
101
class TestFtpFileTransfer(unittest.TestCase):
102
103
    def setUp(self):
104
        self.filename = 'makeme.zip'
105
        self.ftp_url = FTP_URL_TEMPLATE.format_map(MOCK_FTP_CONFIG)
106
        self.source_uri = urljoin(self.ftp_url, 'some_dir/some_file.zip')
107
108
    @mock.patch('foil.ftp.urllib.request.urlopen')
109
    def test_create_target_directory(self, mock_urlopen):
110
        mock_urlopen.side_effect = mock_url_open
111
112
        with tempfile.TemporaryDirectory(prefix='ftp_trans_') as temp_directory:
113
            target_uri = os.path.join(temp_directory, 'some_dir', self.filename)
114
115
            download_ftp_url(self.source_uri, target_uri)
116
117
            with open(target_uri, 'rb') as result_file:
118
                result = result_file.read()
119
120
        self.assertEqual(FILE_CONTENT, result)
121
122
        if os.path.exists(temp_directory):
123
            os.unlink(temp_directory)
124