Skip to content

Commit 35ef056

Browse files
committed
Add tests for ngclient/fetcher
Add tests for the file/data download. Signed-off-by: Teodora Sechkova <[email protected]>
1 parent 86d647b commit 35ef056

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed

tests/test_fetcher_ng.py

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright 2021, New York University and the TUF contributors
4+
# SPDX-License-Identifier: MIT OR Apache-2.0
5+
6+
"""Unit test for RequestsFetcher.
7+
"""
8+
9+
import io
10+
import logging
11+
import os
12+
import sys
13+
import unittest
14+
import tempfile
15+
import math
16+
17+
from tests import utils
18+
from tuf import exceptions, unittest_toolbox
19+
from tuf.ngclient._internal.requests_fetcher import RequestsFetcher
20+
21+
logger = logging.getLogger(__name__)
22+
23+
24+
class TestFetcher(unittest_toolbox.Modified_TestCase):
25+
26+
@classmethod
27+
def setUpClass(cls):
28+
# Launch a SimpleHTTPServer (serves files in the current dir).
29+
cls.server_process_handler = utils.TestServerProcess(log=logger)
30+
31+
@classmethod
32+
def tearDownClass(cls):
33+
# Stop server process and perform clean up.
34+
cls.server_process_handler.clean()
35+
36+
def setUp(self):
37+
"""
38+
Create a temporary file and launch a simple server in the
39+
current working directory.
40+
"""
41+
42+
unittest_toolbox.Modified_TestCase.setUp(self)
43+
44+
# Making a temporary data file.
45+
current_dir = os.getcwd()
46+
target_filepath = self.make_temp_data_file(directory=current_dir)
47+
48+
self.target_fileobj = open(target_filepath, "r")
49+
self.file_contents = self.target_fileobj.read()
50+
self.file_length = len(self.file_contents)
51+
self.rel_target_filepath = os.path.basename(target_filepath)
52+
self.url = f"http://{utils.TEST_HOST_ADDRESS}:{str(self.server_process_handler.port)}/{self.rel_target_filepath}"
53+
54+
# Instantiate a concrete instance of FetcherInterface
55+
self.fetcher = RequestsFetcher()
56+
57+
def tearDown(self):
58+
self.target_fileobj.close()
59+
# Remove temporary directory
60+
unittest_toolbox.Modified_TestCase.tearDown(self)
61+
62+
# Simple fetch.
63+
def test_fetch(self):
64+
with tempfile.TemporaryFile() as temp_file:
65+
for chunk in self.fetcher.fetch(self.url):
66+
temp_file.write(chunk)
67+
68+
temp_file.seek(0)
69+
self.assertEqual(
70+
self.file_contents, temp_file.read().decode("utf-8")
71+
)
72+
73+
# URL data downloaded in more than one chunk
74+
def test_fetch_in_chunks(self):
75+
# Set a smaller chunk size to ensure that the file will be downloaded
76+
# in more than one chunk
77+
self.fetcher.chunk_size = 4
78+
79+
# expected_chunks_count: 3
80+
expected_chunks_count = math.ceil(
81+
self.file_length / self.fetcher.chunk_size
82+
)
83+
self.assertEqual(expected_chunks_count, 3)
84+
85+
chunks_count = 0
86+
with tempfile.TemporaryFile() as temp_file:
87+
for chunk in self.fetcher.fetch(self.url):
88+
temp_file.write(chunk)
89+
chunks_count += 1
90+
91+
temp_file.seek(0)
92+
self.assertEqual(
93+
self.file_contents, temp_file.read().decode("utf-8")
94+
)
95+
# Check that we calculate chunks as expected
96+
self.assertEqual(chunks_count, expected_chunks_count)
97+
98+
# Incorrect URL parsing
99+
def test_url_parsing(self):
100+
with self.assertRaises(exceptions.URLParsingError):
101+
self.fetcher.fetch(self.random_string())
102+
103+
# File not found error
104+
def test_http_error(self):
105+
with self.assertRaises(exceptions.FetcherHTTPError) as cm:
106+
self.url = f"http://{utils.TEST_HOST_ADDRESS}:{str(self.server_process_handler.port)}/non-existing-path"
107+
self.fetcher.fetch(self.url)
108+
self.assertEqual(cm.exception.status_code, 404)
109+
110+
# Simple bytes download
111+
def test_download_bytes(self):
112+
data = self.fetcher.download_bytes(self.url, self.file_length)
113+
self.assertEqual(self.file_contents, data.decode("utf-8"))
114+
115+
# Download file smaller than required max_length
116+
def test_download_bytes_upper_length(self):
117+
data = self.fetcher.download_bytes(self.url, self.file_length + 4)
118+
self.assertEqual(self.file_contents, data.decode("utf-8"))
119+
120+
# Download a file bigger than expected
121+
def test_download_bytes_length_mismatch(self):
122+
with self.assertRaises(exceptions.DownloadLengthMismatchError):
123+
self.fetcher.download_bytes(self.url, self.file_length - 4)
124+
125+
# Simple file download
126+
def test_download_file(self):
127+
with self.fetcher.download_file(
128+
self.url, self.file_length
129+
) as temp_file:
130+
temp_file.seek(0, io.SEEK_END)
131+
self.assertEqual(self.file_length, temp_file.tell())
132+
133+
# Download file smaller than required max_length
134+
def test_download_file_upper_length(self):
135+
with self.fetcher.download_file(
136+
self.url, self.file_length + 4
137+
) as temp_file:
138+
temp_file.seek(0, io.SEEK_END)
139+
self.assertEqual(self.file_length, temp_file.tell())
140+
141+
# Download a file bigger than expected
142+
def test_download_file_length_mismatch(self):
143+
with self.assertRaises(exceptions.DownloadLengthMismatchError):
144+
yield self.fetcher.download_file(self.url, self.file_length - 4)
145+
146+
147+
# Run unit test.
148+
if __name__ == "__main__":
149+
utils.configure_test_logging(sys.argv)
150+
unittest.main()

0 commit comments

Comments
 (0)