Coverage for mlos_bench/mlos_bench/tests/services/remote/azure/azure_fileshare_test.py: 99%
110 statements
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-21 01:50 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-21 01:50 +0000
1#
2# Copyright (c) Microsoft Corporation.
3# Licensed under the MIT License.
4#
5"""Tests for mlos_bench.services.remote.azure.azure_fileshare."""
7import os
8from unittest.mock import MagicMock, Mock, call, patch
10from mlos_bench.services.remote.azure.azure_fileshare import AzureFileShareService
12# pylint: disable=missing-function-docstring
13# pylint: disable=too-many-arguments
14# pylint: disable=unused-argument
17@patch("mlos_bench.services.remote.azure.azure_fileshare.open")
18@patch("mlos_bench.services.remote.azure.azure_fileshare.os.makedirs")
19def test_download_file(
20 mock_makedirs: MagicMock,
21 mock_open: MagicMock,
22 azure_fileshare: AzureFileShareService,
23) -> None:
24 filename = "test.csv"
25 remote_folder = "a/remote/folder"
26 local_folder = "some/local/folder"
27 remote_path = f"{remote_folder}/{filename}"
28 local_path = f"{local_folder}/{filename}"
30 config: dict = {}
31 with (
32 patch.object(azure_fileshare, "_share_client") as mock_share_client,
33 patch.object(mock_share_client, "get_file_client") as mock_get_file_client,
34 patch.object(mock_share_client, "get_directory_client") as mock_get_directory_client,
35 ):
37 mock_get_directory_client.return_value = Mock(exists=Mock(return_value=False))
39 azure_fileshare.download(config, remote_path, local_path)
41 mock_get_file_client.assert_called_with(remote_path)
43 mock_makedirs.assert_called_with(
44 local_folder,
45 exist_ok=True,
46 )
47 open_path, open_mode = mock_open.call_args.args
48 assert os.path.abspath(local_path) == os.path.abspath(open_path)
49 assert open_mode == "wb"
52def make_dir_client_returns(remote_folder: str) -> dict:
53 return {
54 remote_folder: Mock(
55 exists=Mock(return_value=True),
56 list_directories_and_files=Mock(
57 return_value=[
58 {"name": "a_folder", "is_directory": True},
59 {"name": "a_file_1.csv", "is_directory": False},
60 ]
61 ),
62 ),
63 f"{remote_folder}/a_folder": Mock(
64 exists=Mock(return_value=True),
65 list_directories_and_files=Mock(
66 return_value=[
67 {"name": "a_file_2.csv", "is_directory": False},
68 ]
69 ),
70 ),
71 f"{remote_folder}/a_file_1.csv": Mock(exists=Mock(return_value=False)),
72 f"{remote_folder}/a_folder/a_file_2.csv": Mock(exists=Mock(return_value=False)),
73 }
76@patch("mlos_bench.services.remote.azure.azure_fileshare.open")
77@patch("mlos_bench.services.remote.azure.azure_fileshare.os.makedirs")
78def test_download_folder_non_recursive(
79 mock_makedirs: MagicMock,
80 mock_open: MagicMock,
81 azure_fileshare: AzureFileShareService,
82) -> None:
83 remote_folder = "a/remote/folder"
84 local_folder = "some/local/folder"
85 dir_client_returns = make_dir_client_returns(remote_folder)
86 mock_share_client = azure_fileshare._share_client # pylint: disable=protected-access
88 config: dict = {}
89 with (
90 patch.object(azure_fileshare, "_share_client") as mock_share_client,
91 patch.object(mock_share_client, "get_directory_client") as mock_get_directory_client,
92 patch.object(mock_share_client, "get_file_client") as mock_get_file_client,
93 ):
95 mock_get_directory_client.side_effect = lambda x: dir_client_returns[x]
97 azure_fileshare.download(config, remote_folder, local_folder, recursive=False)
99 mock_get_file_client.assert_called_with(
100 f"{remote_folder}/a_file_1.csv",
101 )
102 mock_get_directory_client.assert_has_calls(
103 [
104 call(remote_folder),
105 call(f"{remote_folder}/a_file_1.csv"),
106 ],
107 any_order=True,
108 )
111@patch("mlos_bench.services.remote.azure.azure_fileshare.open")
112@patch("mlos_bench.services.remote.azure.azure_fileshare.os.makedirs")
113def test_download_folder_recursive(
114 mock_makedirs: MagicMock,
115 mock_open: MagicMock,
116 azure_fileshare: AzureFileShareService,
117) -> None:
118 remote_folder = "a/remote/folder"
119 local_folder = "some/local/folder"
120 dir_client_returns = make_dir_client_returns(remote_folder)
122 config: dict = {}
123 with (
124 patch.object(azure_fileshare, "_share_client") as mock_share_client,
125 patch.object(mock_share_client, "get_directory_client") as mock_get_directory_client,
126 patch.object(mock_share_client, "get_file_client") as mock_get_file_client,
127 ):
128 mock_get_directory_client.side_effect = lambda x: dir_client_returns[x]
129 azure_fileshare.download(config, remote_folder, local_folder, recursive=True)
131 mock_get_file_client.assert_has_calls(
132 [
133 call(f"{remote_folder}/a_file_1.csv"),
134 call(f"{remote_folder}/a_folder/a_file_2.csv"),
135 ],
136 any_order=True,
137 )
138 mock_get_directory_client.assert_has_calls(
139 [
140 call(remote_folder),
141 call(f"{remote_folder}/a_file_1.csv"),
142 call(f"{remote_folder}/a_folder"),
143 call(f"{remote_folder}/a_folder/a_file_2.csv"),
144 ],
145 any_order=True,
146 )
149@patch("mlos_bench.services.remote.azure.azure_fileshare.open")
150@patch("mlos_bench.services.remote.azure.azure_fileshare.os.path.isdir")
151def test_upload_file(
152 mock_isdir: MagicMock,
153 mock_open: MagicMock,
154 azure_fileshare: AzureFileShareService,
155) -> None:
156 filename = "test.csv"
157 remote_folder = "a/remote/folder"
158 local_folder = "some/local/folder"
159 remote_path = f"{remote_folder}/{filename}"
160 local_path = f"{local_folder}/{filename}"
161 mock_share_client = azure_fileshare._share_client # pylint: disable=protected-access
162 mock_isdir.return_value = False
164 config: dict = {}
165 with (
166 patch.object(azure_fileshare, "_share_client") as mock_share_client,
167 patch.object(mock_share_client, "get_file_client") as mock_get_file_client,
168 ):
169 azure_fileshare.upload(config, local_path, remote_path)
171 mock_get_file_client.assert_called_with(remote_path)
172 open_path, open_mode = mock_open.call_args.args
173 assert os.path.abspath(local_path) == os.path.abspath(open_path)
174 assert open_mode == "rb"
177class MyDirEntry:
178 # pylint: disable=too-few-public-methods
179 """Dummy class for os.DirEntry."""
181 def __init__(self, name: str, is_a_dir: bool):
182 self.name = name
183 self.is_a_dir = is_a_dir
185 def is_dir(self) -> bool:
186 return self.is_a_dir
189def make_scandir_returns(local_folder: str) -> dict:
190 return {
191 local_folder: [
192 MyDirEntry("a_folder", True),
193 MyDirEntry("a_file_1.csv", False),
194 ],
195 f"{local_folder}/a_folder": [
196 MyDirEntry("a_file_2.csv", False),
197 ],
198 }
201def make_isdir_returns(local_folder: str) -> dict:
202 return {
203 local_folder: True,
204 f"{local_folder}/a_file_1.csv": False,
205 f"{local_folder}/a_folder": True,
206 f"{local_folder}/a_folder/a_file_2.csv": False,
207 }
210def process_paths(input_path: str) -> str:
211 skip_prefix = os.getcwd()
212 # Remove prefix from os.path.abspath if there
213 if input_path == os.path.abspath(input_path):
214 result = input_path[(len(skip_prefix) + 1) :]
215 else:
216 result = input_path
217 # Change file seps to unix-style
218 return result.replace("\\", "/")
221@patch("mlos_bench.services.remote.azure.azure_fileshare.open")
222@patch("mlos_bench.services.remote.azure.azure_fileshare.os.path.isdir")
223@patch("mlos_bench.services.remote.azure.azure_fileshare.os.scandir")
224def test_upload_directory_non_recursive(
225 mock_scandir: MagicMock,
226 mock_isdir: MagicMock,
227 mock_open: MagicMock,
228 azure_fileshare: AzureFileShareService,
229) -> None:
230 remote_folder = "a/remote/folder"
231 local_folder = "some/local/folder"
232 scandir_returns = make_scandir_returns(local_folder)
233 isdir_returns = make_isdir_returns(local_folder)
234 mock_scandir.side_effect = lambda x: scandir_returns[process_paths(x)]
235 mock_isdir.side_effect = lambda x: isdir_returns[process_paths(x)]
236 mock_share_client = azure_fileshare._share_client # pylint: disable=protected-access
238 config: dict = {}
239 with (
240 patch.object(azure_fileshare, "_share_client") as mock_share_client,
241 patch.object(mock_share_client, "get_file_client") as mock_get_file_client,
242 ):
243 azure_fileshare.upload(config, local_folder, remote_folder, recursive=False)
245 mock_get_file_client.assert_called_with(f"{remote_folder}/a_file_1.csv")
248@patch("mlos_bench.services.remote.azure.azure_fileshare.open")
249@patch("mlos_bench.services.remote.azure.azure_fileshare.os.path.isdir")
250@patch("mlos_bench.services.remote.azure.azure_fileshare.os.scandir")
251def test_upload_directory_recursive(
252 mock_scandir: MagicMock,
253 mock_isdir: MagicMock,
254 mock_open: MagicMock,
255 azure_fileshare: AzureFileShareService,
256) -> None:
257 remote_folder = "a/remote/folder"
258 local_folder = "some/local/folder"
259 scandir_returns = make_scandir_returns(local_folder)
260 isdir_returns = make_isdir_returns(local_folder)
261 mock_scandir.side_effect = lambda x: scandir_returns[process_paths(x)]
262 mock_isdir.side_effect = lambda x: isdir_returns[process_paths(x)]
263 mock_share_client = azure_fileshare._share_client # pylint: disable=protected-access
265 config: dict = {}
266 with (
267 patch.object(azure_fileshare, "_share_client") as mock_share_client,
268 patch.object(mock_share_client, "get_file_client") as mock_get_file_client,
269 ):
270 azure_fileshare.upload(config, local_folder, remote_folder, recursive=True)
272 mock_get_file_client.assert_has_calls(
273 [
274 call(f"{remote_folder}/a_file_1.csv"),
275 call(f"{remote_folder}/a_folder/a_file_2.csv"),
276 ],
277 any_order=True,
278 )