blob: 86b0491374f01b2c026cbb5829987e7a5b7d0eb0 [file] [log] [blame]
Eduardo Sousaf5119a82018-04-25 17:55:17 +01001import io
2import logging
3import http
4import os
5import pytest
6import tarfile
7import tempfile
8import uuid
9import shutil
10
11from osm_common.fsbase import FsException
12from osm_common.fslocal import FsLocal
13
14__author__ = "Eduardo Sousa <eduardosousa@av.it.pt>"
15
tiernob20a9022018-05-22 12:07:05 +020016
Eduardo Sousaf5119a82018-04-25 17:55:17 +010017def valid_path():
18 return tempfile.gettempdir() + '/'
19
tiernob20a9022018-05-22 12:07:05 +020020
Eduardo Sousaf5119a82018-04-25 17:55:17 +010021def invalid_path():
22 return '/#tweeter/'
23
tiernob20a9022018-05-22 12:07:05 +020024
tierno1e9a3292018-11-05 18:18:45 +010025@pytest.fixture(scope="function", params=[True, False])
26def fs_local(request):
27 fs = FsLocal(lock=request.param)
Eduardo Sousaf5119a82018-04-25 17:55:17 +010028 fs.fs_connect({'path': valid_path()})
Eduardo Sousaf5119a82018-04-25 17:55:17 +010029 return fs
30
tiernob20a9022018-05-22 12:07:05 +020031
Eduardo Sousaf5119a82018-04-25 17:55:17 +010032def fs_connect_exception_message(path):
33 return "storage exception Invalid configuration param at '[storage]': path '{}' does not exist".format(path)
34
tiernob20a9022018-05-22 12:07:05 +020035
Eduardo Sousaf5119a82018-04-25 17:55:17 +010036def file_open_file_not_found_exception(storage):
37 f = storage if isinstance(storage, str) else '/'.join(storage)
38 return "storage exception File {} does not exist".format(f)
39
tiernob20a9022018-05-22 12:07:05 +020040
Eduardo Sousaf5119a82018-04-25 17:55:17 +010041def file_open_io_exception(storage):
42 f = storage if isinstance(storage, str) else '/'.join(storage)
43 return "storage exception File {} cannot be opened".format(f)
44
tiernob20a9022018-05-22 12:07:05 +020045
Eduardo Sousaf5119a82018-04-25 17:55:17 +010046def dir_ls_not_a_directory_exception(storage):
47 f = storage if isinstance(storage, str) else '/'.join(storage)
48 return "storage exception File {} does not exist".format(f)
49
tiernob20a9022018-05-22 12:07:05 +020050
Eduardo Sousaf5119a82018-04-25 17:55:17 +010051def dir_ls_io_exception(storage):
52 f = storage if isinstance(storage, str) else '/'.join(storage)
53 return "storage exception File {} cannot be opened".format(f)
54
tiernob20a9022018-05-22 12:07:05 +020055
Eduardo Sousaf5119a82018-04-25 17:55:17 +010056def file_delete_exception_message(storage):
57 return "storage exception File {} does not exist".format(storage)
58
tiernob20a9022018-05-22 12:07:05 +020059
Eduardo Sousaf5119a82018-04-25 17:55:17 +010060def test_constructor_without_logger():
61 fs = FsLocal()
Eduardo Sousaf5119a82018-04-25 17:55:17 +010062 assert fs.logger == logging.getLogger('fs')
63 assert fs.path is None
64
tiernob20a9022018-05-22 12:07:05 +020065
Eduardo Sousaf5119a82018-04-25 17:55:17 +010066def test_constructor_with_logger():
67 logger_name = 'fs_local'
Eduardo Sousaf5119a82018-04-25 17:55:17 +010068 fs = FsLocal(logger_name=logger_name)
Eduardo Sousaf5119a82018-04-25 17:55:17 +010069 assert fs.logger == logging.getLogger(logger_name)
70 assert fs.path is None
71
tiernob20a9022018-05-22 12:07:05 +020072
Eduardo Sousa5ffda642018-05-09 19:42:00 +010073def test_get_params(fs_local):
74 params = fs_local.get_params()
Eduardo Sousa5ffda642018-05-09 19:42:00 +010075 assert len(params) == 2
76 assert "fs" in params
77 assert "path" in params
78 assert params["fs"] == "local"
79 assert params["path"] == valid_path()
80
tiernob20a9022018-05-22 12:07:05 +020081
Eduardo Sousaf5119a82018-04-25 17:55:17 +010082@pytest.mark.parametrize("config, exp_logger, exp_path", [
83 ({'logger_name': 'fs_local', 'path': valid_path()}, 'fs_local', valid_path()),
84 ({'logger_name': 'fs_local', 'path': valid_path()[:-1]}, 'fs_local', valid_path()),
85 ({'path': valid_path()}, 'fs', valid_path()),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +010086 ({'path': valid_path()[:-1]}, 'fs', valid_path())])
Eduardo Sousaf5119a82018-04-25 17:55:17 +010087def test_fs_connect_with_valid_config(config, exp_logger, exp_path):
88 fs = FsLocal()
89 fs.fs_connect(config)
Eduardo Sousaf5119a82018-04-25 17:55:17 +010090 assert fs.logger == logging.getLogger(exp_logger)
91 assert fs.path == exp_path
92
tiernob20a9022018-05-22 12:07:05 +020093
Eduardo Sousaf5119a82018-04-25 17:55:17 +010094@pytest.mark.parametrize("config, exp_exception_message", [
95 ({'logger_name': 'fs_local', 'path': invalid_path()}, fs_connect_exception_message(invalid_path())),
96 ({'logger_name': 'fs_local', 'path': invalid_path()[:-1]}, fs_connect_exception_message(invalid_path()[:-1])),
97 ({'path': invalid_path()}, fs_connect_exception_message(invalid_path())),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +010098 ({'path': invalid_path()[:-1]}, fs_connect_exception_message(invalid_path()[:-1]))])
Eduardo Sousaf5119a82018-04-25 17:55:17 +010099def test_fs_connect_with_invalid_path(config, exp_exception_message):
100 fs = FsLocal()
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100101 with pytest.raises(FsException) as excinfo:
102 fs.fs_connect(config)
103 assert str(excinfo.value) == exp_exception_message
104
tiernob20a9022018-05-22 12:07:05 +0200105
Eduardo Sousa5ffda642018-05-09 19:42:00 +0100106def test_fs_disconnect(fs_local):
107 fs_local.fs_disconnect()
108
tiernob20a9022018-05-22 12:07:05 +0200109
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100110def test_mkdir_with_valid_path(fs_local):
111 folder_name = str(uuid.uuid4())
112 folder_path = valid_path() + folder_name
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100113 fs_local.mkdir(folder_name)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100114 assert os.path.exists(folder_path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100115 os.rmdir(folder_path)
116
tiernob20a9022018-05-22 12:07:05 +0200117
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100118def test_mkdir_with_exception(fs_local):
119 folder_name = str(uuid.uuid4())
120 folder_path = valid_path() + folder_name
121 os.mkdir(folder_path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100122 with pytest.raises(FsException) as excinfo:
123 fs_local.mkdir(folder_name)
124 assert excinfo.value.http_code == http.HTTPStatus.INTERNAL_SERVER_ERROR
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100125 os.rmdir(folder_path)
126
tiernob20a9022018-05-22 12:07:05 +0200127
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100128@pytest.mark.parametrize("storage, mode, expected", [
129 (str(uuid.uuid4()), 'file', False),
130 ([str(uuid.uuid4())], 'file', False),
131 (str(uuid.uuid4()), 'dir', False),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100132 ([str(uuid.uuid4())], 'dir', False)])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100133def test_file_exists_returns_false(fs_local, storage, mode, expected):
134 assert fs_local.file_exists(storage, mode) == expected
135
tiernob20a9022018-05-22 12:07:05 +0200136
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100137@pytest.mark.parametrize("storage, mode, expected", [
138 (str(uuid.uuid4()), 'file', True),
139 ([str(uuid.uuid4())], 'file', True),
140 (str(uuid.uuid4()), 'dir', True),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100141 ([str(uuid.uuid4())], 'dir', True)])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100142def test_file_exists_returns_true(fs_local, storage, mode, expected):
143 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100144 if mode == 'file':
145 os.mknod(path)
146 elif mode == 'dir':
147 os.mkdir(path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100148 assert fs_local.file_exists(storage, mode) == expected
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100149 if mode == 'file':
150 os.remove(path)
151 elif mode == 'dir':
152 os.rmdir(path)
153
tiernob20a9022018-05-22 12:07:05 +0200154
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100155@pytest.mark.parametrize("storage, mode", [
156 (str(uuid.uuid4()), 'file'),
157 ([str(uuid.uuid4())], 'file'),
158 (str(uuid.uuid4()), 'dir'),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100159 ([str(uuid.uuid4())], 'dir')])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100160def test_file_size(fs_local, storage, mode):
161 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100162 if mode == 'file':
163 os.mknod(path)
164 elif mode == 'dir':
165 os.mkdir(path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100166 size = os.path.getsize(path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100167 assert fs_local.file_size(storage) == size
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100168 if mode == 'file':
169 os.remove(path)
170 elif mode == 'dir':
171 os.rmdir(path)
172
tiernob20a9022018-05-22 12:07:05 +0200173
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100174@pytest.mark.parametrize("files, path", [
175 (['foo', 'bar', 'foobar'], str(uuid.uuid4())),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100176 (['foo', 'bar', 'foobar'], [str(uuid.uuid4())])])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100177def test_file_extract(fs_local, files, path):
178 for f in files:
179 os.mknod(valid_path() + f)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100180 tar_path = valid_path() + str(uuid.uuid4()) + '.tar'
181 with tarfile.open(tar_path, 'w') as tar:
182 for f in files:
183 tar.add(valid_path() + f, arcname=f)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100184 with tarfile.open(tar_path, 'r') as tar:
185 fs_local.file_extract(tar, path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100186 extracted_path = valid_path() + (path if isinstance(path, str) else '/'.join(path))
187 ls_dir = os.listdir(extracted_path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100188 assert len(ls_dir) == len(files)
189 for f in files:
190 assert f in ls_dir
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100191 os.remove(tar_path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100192 for f in files:
193 os.remove(valid_path() + f)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100194 shutil.rmtree(extracted_path)
195
tiernob20a9022018-05-22 12:07:05 +0200196
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100197@pytest.mark.parametrize("storage, mode", [
198 (str(uuid.uuid4()), 'r'),
199 (str(uuid.uuid4()), 'w'),
200 (str(uuid.uuid4()), 'a'),
201 (str(uuid.uuid4()), 'rb'),
202 (str(uuid.uuid4()), 'wb'),
203 (str(uuid.uuid4()), 'ab'),
204 ([str(uuid.uuid4())], 'r'),
205 ([str(uuid.uuid4())], 'w'),
206 ([str(uuid.uuid4())], 'a'),
207 ([str(uuid.uuid4())], 'rb'),
208 ([str(uuid.uuid4())], 'wb'),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100209 ([str(uuid.uuid4())], 'ab')])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100210def test_file_open(fs_local, storage, mode):
211 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100212 os.mknod(path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100213 file_obj = fs_local.file_open(storage, mode)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100214 assert isinstance(file_obj, io.IOBase)
tiernob20a9022018-05-22 12:07:05 +0200215 assert file_obj.closed is False
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100216 os.remove(path)
217
tiernob20a9022018-05-22 12:07:05 +0200218
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100219@pytest.mark.parametrize("storage, mode", [
220 (str(uuid.uuid4()), 'r'),
221 (str(uuid.uuid4()), 'rb'),
222 ([str(uuid.uuid4())], 'r'),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100223 ([str(uuid.uuid4())], 'rb')])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100224def test_file_open_file_not_found_exception(fs_local, storage, mode):
225 with pytest.raises(FsException) as excinfo:
226 fs_local.file_open(storage, mode)
227 assert str(excinfo.value) == file_open_file_not_found_exception(storage)
228 assert excinfo.value.http_code == http.HTTPStatus.NOT_FOUND
229
tiernob20a9022018-05-22 12:07:05 +0200230
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100231@pytest.mark.parametrize("storage, mode", [
232 (str(uuid.uuid4()), 'r'),
233 (str(uuid.uuid4()), 'w'),
234 (str(uuid.uuid4()), 'a'),
235 (str(uuid.uuid4()), 'rb'),
236 (str(uuid.uuid4()), 'wb'),
237 (str(uuid.uuid4()), 'ab'),
238 ([str(uuid.uuid4())], 'r'),
239 ([str(uuid.uuid4())], 'w'),
240 ([str(uuid.uuid4())], 'a'),
241 ([str(uuid.uuid4())], 'rb'),
242 ([str(uuid.uuid4())], 'wb'),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100243 ([str(uuid.uuid4())], 'ab')])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100244def test_file_open_io_error(fs_local, storage, mode):
245 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100246 os.mknod(path)
247 os.chmod(path, 0)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100248 with pytest.raises(FsException) as excinfo:
249 fs_local.file_open(storage, mode)
250 assert str(excinfo.value) == file_open_io_exception(storage)
251 assert excinfo.value.http_code == http.HTTPStatus.BAD_REQUEST
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100252 os.remove(path)
253
tiernob20a9022018-05-22 12:07:05 +0200254
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100255@pytest.mark.parametrize("storage, with_files", [
256 (str(uuid.uuid4()), True),
257 (str(uuid.uuid4()), False),
258 ([str(uuid.uuid4())], True),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100259 ([str(uuid.uuid4())], False)])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100260def test_dir_ls(fs_local, storage, with_files):
261 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100262 os.mkdir(path)
tiernob20a9022018-05-22 12:07:05 +0200263 if with_files is True:
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100264 file_name = str(uuid.uuid4())
265 file_path = path + '/' + file_name
266 os.mknod(file_path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100267 result = fs_local.dir_ls(storage)
268
tiernob20a9022018-05-22 12:07:05 +0200269 if with_files is True:
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100270 assert len(result) == 1
271 assert result[0] == file_name
272 else:
273 assert len(result) == 0
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100274 shutil.rmtree(path)
275
tiernob20a9022018-05-22 12:07:05 +0200276
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100277@pytest.mark.parametrize("storage", [
278 (str(uuid.uuid4())),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100279 ([str(uuid.uuid4())])])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100280def test_dir_ls_with_not_a_directory_error(fs_local, storage):
281 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100282 os.mknod(path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100283 with pytest.raises(FsException) as excinfo:
284 fs_local.dir_ls(storage)
285 assert str(excinfo.value) == dir_ls_not_a_directory_exception(storage)
286 assert excinfo.value.http_code == http.HTTPStatus.NOT_FOUND
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100287 os.remove(path)
288
tiernob20a9022018-05-22 12:07:05 +0200289
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100290@pytest.mark.parametrize("storage", [
291 (str(uuid.uuid4())),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100292 ([str(uuid.uuid4())])])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100293def test_dir_ls_with_io_error(fs_local, storage):
294 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100295 os.mkdir(path)
296 os.chmod(path, 0)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100297 with pytest.raises(FsException) as excinfo:
298 fs_local.dir_ls(storage)
299 assert str(excinfo.value) == dir_ls_io_exception(storage)
300 assert excinfo.value.http_code == http.HTTPStatus.BAD_REQUEST
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100301 os.rmdir(path)
302
tiernob20a9022018-05-22 12:07:05 +0200303
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100304@pytest.mark.parametrize("storage, with_files, ignore_non_exist", [
305 (str(uuid.uuid4()), True, True),
306 (str(uuid.uuid4()), False, True),
307 (str(uuid.uuid4()), True, False),
308 (str(uuid.uuid4()), False, False),
309 ([str(uuid.uuid4())], True, True),
310 ([str(uuid.uuid4())], False, True),
311 ([str(uuid.uuid4())], True, False),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100312 ([str(uuid.uuid4())], False, False)])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100313def test_file_delete_with_dir(fs_local, storage, with_files, ignore_non_exist):
314 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100315 os.mkdir(path)
tiernob20a9022018-05-22 12:07:05 +0200316 if with_files is True:
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100317 file_path = path + '/' + str(uuid.uuid4())
318 os.mknod(file_path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100319 fs_local.file_delete(storage, ignore_non_exist)
tiernob20a9022018-05-22 12:07:05 +0200320 assert os.path.exists(path) is False
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100321
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100322
323@pytest.mark.parametrize("storage", [
324 (str(uuid.uuid4())),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100325 ([str(uuid.uuid4())])])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100326def test_file_delete_expect_exception(fs_local, storage):
327 with pytest.raises(FsException) as excinfo:
328 fs_local.file_delete(storage)
329 assert str(excinfo.value) == file_delete_exception_message(storage)
330 assert excinfo.value.http_code == http.HTTPStatus.NOT_FOUND
331
tiernob20a9022018-05-22 12:07:05 +0200332
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100333@pytest.mark.parametrize("storage", [
334 (str(uuid.uuid4())),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100335 ([str(uuid.uuid4())])])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100336def test_file_delete_no_exception(fs_local, storage):
337 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100338 fs_local.file_delete(storage, ignore_non_exist=True)
tiernob20a9022018-05-22 12:07:05 +0200339 assert os.path.exists(path) is False