1616import unittest
1717import zipfile
1818from pathlib import Path
19- from urllib .error import ContentTooShortError , HTTPError
2019
2120from parameterized import parameterized
2221
2322from monai .apps import download_and_extract , download_url , extractall
23+ from monai .apps .utils import HashCheckError
2424from tests .test_utils import SkipIfNoModule , skip_if_downloading_fails , skip_if_quick , testing_data_config
2525
2626
2727@SkipIfNoModule ("requests" )
2828class TestDownloadAndExtract (unittest .TestCase ):
29+ def setUp (self ):
30+ self .testing_dir = Path (__file__ ).parents [1 ] / "testing_data"
31+ self .config = testing_data_config ("images" , "mednist" )
32+ self .url = self .config ["url" ]
33+ self .hash_val = self .config ["hash_val" ]
34+ self .hash_type = self .config ["hash_type" ]
35+
2936 @skip_if_quick
30- def test_actions (self ):
31- testing_dir = Path (__file__ ).parents [1 ] / "testing_data"
32- config_dict = testing_data_config ("images" , "mednist" )
33- url = config_dict ["url" ]
34- filepath = Path (testing_dir ) / "MedNIST.tar.gz"
35- output_dir = Path (testing_dir )
36- hash_val , hash_type = config_dict ["hash_val" ], config_dict ["hash_type" ]
37+ def test_download_and_extract_success (self ):
38+ """End-to-end: download and extract should succeed with correct hash."""
39+ filepath = self .testing_dir / "MedNIST.tar.gz"
40+ output_dir = self .testing_dir
41+
3742 with skip_if_downloading_fails ():
38- download_and_extract (url , filepath , output_dir , hash_val = hash_val , hash_type = hash_type )
39- download_and_extract (url , filepath , output_dir , hash_val = hash_val , hash_type = hash_type )
43+ download_and_extract (self .url , filepath , output_dir , hash_val = self .hash_val , hash_type = self .hash_type )
4044
41- wrong_md5 = "0"
42- with self .assertLogs (logger = "monai.apps" , level = "ERROR" ):
43- try :
44- download_url (url , filepath , wrong_md5 )
45- except (ContentTooShortError , HTTPError , RuntimeError ) as e :
46- if isinstance (e , RuntimeError ):
47- # FIXME: skip MD5 check as current downloading method may fail
48- self .assertTrue (str (e ).startswith ("md5 check" ))
49- return # skipping this test due the network connection errors
50-
51- try :
52- extractall (filepath , output_dir , wrong_md5 )
53- except RuntimeError as e :
54- self .assertTrue (str (e ).startswith ("md5 check" ))
45+ self .assertTrue (filepath .exists (), "Downloaded file does not exist" )
46+ self .assertTrue (any (output_dir .iterdir ()), "Extraction output is empty" )
47+
48+ @skip_if_quick
49+ def test_download_url_hash_mismatch (self ):
50+ """download_url should raise HashCheckError on hash mismatch."""
51+ filepath = self .testing_dir / "MedNIST.tar.gz"
52+
53+ with skip_if_downloading_fails ():
54+ # First ensure file is downloaded correctly
55+ download_url (self .url , filepath , hash_val = self .hash_val , hash_type = self .hash_type )
56+
57+ # Now test incorrect hash
58+ with self .assertRaises (HashCheckError ):
59+ download_url (self .url , filepath , hash_val = "0" * len (self .hash_val ), hash_type = self .hash_type )
5560
5661 @skip_if_quick
57- @parameterized .expand ((("icon" , "tar" ), ("favicon" , "zip" )))
58- def test_default (self , key , file_type ):
62+ def test_extractall_hash_mismatch (self ):
63+ """extractall should raise HashCheckError when hash is incorrect."""
64+ filepath = self .testing_dir / "MedNIST.tar.gz"
65+ output_dir = self .testing_dir
66+
67+ with skip_if_downloading_fails ():
68+ download_url (self .url , filepath , hash_val = self .hash_val , hash_type = self .hash_type )
69+
70+ with self .assertRaises (HashCheckError ):
71+ extractall (filepath , output_dir , hash_val = "0" * len (self .hash_val ), hash_type = self .hash_type )
72+
73+ @skip_if_quick
74+ @parameterized .expand ([("icon" , "tar" ), ("favicon" , "zip" )])
75+ def test_download_and_extract_various_formats (self , key , file_type ):
76+ """Verify different archive formats download and extract correctly."""
5977 with tempfile .TemporaryDirectory () as tmp_dir :
78+ img_spec = testing_data_config ("images" , key )
79+
6080 with skip_if_downloading_fails ():
61- img_spec = testing_data_config ("images" , key )
6281 download_and_extract (
6382 img_spec ["url" ],
6483 output_dir = tmp_dir ,
@@ -67,6 +86,8 @@ def test_default(self, key, file_type):
6786 file_type = file_type ,
6887 )
6988
89+ self .assertTrue (any (Path (tmp_dir ).iterdir ()), f"Extraction failed for format: { file_type } " )
90+
7091
7192class TestPathTraversalProtection (unittest .TestCase ):
7293 """Test cases for path traversal attack protection in extractall function."""
0 commit comments