blob: 7416cfb4f0f50932027f8b23464a5a9499579ae1 [file] [log] [blame]
Eduardo Sousaa0117812019-02-05 15:57:09 +00001# Copyright 2018 Whitestack, LLC
2# Copyright 2018 Telefonica S.A.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15#
16# For those usages not covered by the Apache License, Version 2.0 please
17# contact: esousa@whitestack.com or alfonso.tiernosepulveda@telefonica.com
18##
19
Eduardo Sousaf5119a82018-04-25 17:55:17 +010020import io
21import logging
22import http
23import os
24import pytest
25import tarfile
26import tempfile
27import uuid
28import shutil
29
30from osm_common.fsbase import FsException
31from osm_common.fslocal import FsLocal
32
33__author__ = "Eduardo Sousa <eduardosousa@av.it.pt>"
34
tiernob20a9022018-05-22 12:07:05 +020035
Eduardo Sousaf5119a82018-04-25 17:55:17 +010036def valid_path():
37 return tempfile.gettempdir() + '/'
38
tiernob20a9022018-05-22 12:07:05 +020039
Eduardo Sousaf5119a82018-04-25 17:55:17 +010040def invalid_path():
41 return '/#tweeter/'
42
tiernob20a9022018-05-22 12:07:05 +020043
tierno1e9a3292018-11-05 18:18:45 +010044@pytest.fixture(scope="function", params=[True, False])
45def fs_local(request):
46 fs = FsLocal(lock=request.param)
Eduardo Sousaf5119a82018-04-25 17:55:17 +010047 fs.fs_connect({'path': valid_path()})
Eduardo Sousaf5119a82018-04-25 17:55:17 +010048 return fs
49
tiernob20a9022018-05-22 12:07:05 +020050
Eduardo Sousaf5119a82018-04-25 17:55:17 +010051def fs_connect_exception_message(path):
52 return "storage exception Invalid configuration param at '[storage]': path '{}' does not exist".format(path)
53
tiernob20a9022018-05-22 12:07:05 +020054
Eduardo Sousaf5119a82018-04-25 17:55:17 +010055def file_open_file_not_found_exception(storage):
56 f = storage if isinstance(storage, str) else '/'.join(storage)
57 return "storage exception File {} does not exist".format(f)
58
tiernob20a9022018-05-22 12:07:05 +020059
Eduardo Sousaf5119a82018-04-25 17:55:17 +010060def file_open_io_exception(storage):
61 f = storage if isinstance(storage, str) else '/'.join(storage)
62 return "storage exception File {} cannot be opened".format(f)
63
tiernob20a9022018-05-22 12:07:05 +020064
Eduardo Sousaf5119a82018-04-25 17:55:17 +010065def dir_ls_not_a_directory_exception(storage):
66 f = storage if isinstance(storage, str) else '/'.join(storage)
67 return "storage exception File {} does not exist".format(f)
68
tiernob20a9022018-05-22 12:07:05 +020069
Eduardo Sousaf5119a82018-04-25 17:55:17 +010070def dir_ls_io_exception(storage):
71 f = storage if isinstance(storage, str) else '/'.join(storage)
72 return "storage exception File {} cannot be opened".format(f)
73
tiernob20a9022018-05-22 12:07:05 +020074
Eduardo Sousaf5119a82018-04-25 17:55:17 +010075def file_delete_exception_message(storage):
76 return "storage exception File {} does not exist".format(storage)
77
tiernob20a9022018-05-22 12:07:05 +020078
Eduardo Sousaf5119a82018-04-25 17:55:17 +010079def test_constructor_without_logger():
80 fs = FsLocal()
Eduardo Sousaf5119a82018-04-25 17:55:17 +010081 assert fs.logger == logging.getLogger('fs')
82 assert fs.path is None
83
tiernob20a9022018-05-22 12:07:05 +020084
Eduardo Sousaf5119a82018-04-25 17:55:17 +010085def test_constructor_with_logger():
86 logger_name = 'fs_local'
Eduardo Sousaf5119a82018-04-25 17:55:17 +010087 fs = FsLocal(logger_name=logger_name)
Eduardo Sousaf5119a82018-04-25 17:55:17 +010088 assert fs.logger == logging.getLogger(logger_name)
89 assert fs.path is None
90
tiernob20a9022018-05-22 12:07:05 +020091
Eduardo Sousa5ffda642018-05-09 19:42:00 +010092def test_get_params(fs_local):
93 params = fs_local.get_params()
Eduardo Sousa5ffda642018-05-09 19:42:00 +010094 assert len(params) == 2
95 assert "fs" in params
96 assert "path" in params
97 assert params["fs"] == "local"
98 assert params["path"] == valid_path()
99
tiernob20a9022018-05-22 12:07:05 +0200100
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100101@pytest.mark.parametrize("config, exp_logger, exp_path", [
102 ({'logger_name': 'fs_local', 'path': valid_path()}, 'fs_local', valid_path()),
103 ({'logger_name': 'fs_local', 'path': valid_path()[:-1]}, 'fs_local', valid_path()),
104 ({'path': valid_path()}, 'fs', valid_path()),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100105 ({'path': valid_path()[:-1]}, 'fs', valid_path())])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100106def test_fs_connect_with_valid_config(config, exp_logger, exp_path):
107 fs = FsLocal()
108 fs.fs_connect(config)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100109 assert fs.logger == logging.getLogger(exp_logger)
110 assert fs.path == exp_path
111
tiernob20a9022018-05-22 12:07:05 +0200112
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100113@pytest.mark.parametrize("config, exp_exception_message", [
114 ({'logger_name': 'fs_local', 'path': invalid_path()}, fs_connect_exception_message(invalid_path())),
115 ({'logger_name': 'fs_local', 'path': invalid_path()[:-1]}, fs_connect_exception_message(invalid_path()[:-1])),
116 ({'path': invalid_path()}, fs_connect_exception_message(invalid_path())),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100117 ({'path': invalid_path()[:-1]}, fs_connect_exception_message(invalid_path()[:-1]))])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100118def test_fs_connect_with_invalid_path(config, exp_exception_message):
119 fs = FsLocal()
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100120 with pytest.raises(FsException) as excinfo:
121 fs.fs_connect(config)
122 assert str(excinfo.value) == exp_exception_message
123
tiernob20a9022018-05-22 12:07:05 +0200124
Eduardo Sousa5ffda642018-05-09 19:42:00 +0100125def test_fs_disconnect(fs_local):
126 fs_local.fs_disconnect()
127
tiernob20a9022018-05-22 12:07:05 +0200128
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100129def test_mkdir_with_valid_path(fs_local):
130 folder_name = str(uuid.uuid4())
131 folder_path = valid_path() + folder_name
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100132 fs_local.mkdir(folder_name)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100133 assert os.path.exists(folder_path)
tiernoc7ac30d2019-01-25 08:56:17 +0000134 # test idempotency
135 fs_local.mkdir(folder_name)
136 assert os.path.exists(folder_path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100137 os.rmdir(folder_path)
138
tiernob20a9022018-05-22 12:07:05 +0200139
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100140def test_mkdir_with_exception(fs_local):
141 folder_name = str(uuid.uuid4())
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100142 with pytest.raises(FsException) as excinfo:
tiernoc7ac30d2019-01-25 08:56:17 +0000143 fs_local.mkdir(folder_name + "/" + folder_name)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100144 assert excinfo.value.http_code == http.HTTPStatus.INTERNAL_SERVER_ERROR
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100145
tiernob20a9022018-05-22 12:07:05 +0200146
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100147@pytest.mark.parametrize("storage, mode, expected", [
148 (str(uuid.uuid4()), 'file', False),
149 ([str(uuid.uuid4())], 'file', False),
150 (str(uuid.uuid4()), 'dir', False),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100151 ([str(uuid.uuid4())], 'dir', False)])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100152def test_file_exists_returns_false(fs_local, storage, mode, expected):
153 assert fs_local.file_exists(storage, mode) == expected
154
tiernob20a9022018-05-22 12:07:05 +0200155
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100156@pytest.mark.parametrize("storage, mode, expected", [
157 (str(uuid.uuid4()), 'file', True),
158 ([str(uuid.uuid4())], 'file', True),
159 (str(uuid.uuid4()), 'dir', True),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100160 ([str(uuid.uuid4())], 'dir', True)])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100161def test_file_exists_returns_true(fs_local, storage, mode, expected):
162 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100163 if mode == 'file':
164 os.mknod(path)
165 elif mode == 'dir':
166 os.mkdir(path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100167 assert fs_local.file_exists(storage, mode) == expected
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("storage, mode", [
175 (str(uuid.uuid4()), 'file'),
176 ([str(uuid.uuid4())], 'file'),
177 (str(uuid.uuid4()), 'dir'),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100178 ([str(uuid.uuid4())], 'dir')])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100179def test_file_size(fs_local, storage, mode):
180 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100181 if mode == 'file':
182 os.mknod(path)
183 elif mode == 'dir':
184 os.mkdir(path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100185 size = os.path.getsize(path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100186 assert fs_local.file_size(storage) == size
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100187 if mode == 'file':
188 os.remove(path)
189 elif mode == 'dir':
190 os.rmdir(path)
191
tiernob20a9022018-05-22 12:07:05 +0200192
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100193@pytest.mark.parametrize("files, path", [
194 (['foo', 'bar', 'foobar'], str(uuid.uuid4())),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100195 (['foo', 'bar', 'foobar'], [str(uuid.uuid4())])])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100196def test_file_extract(fs_local, files, path):
197 for f in files:
198 os.mknod(valid_path() + f)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100199 tar_path = valid_path() + str(uuid.uuid4()) + '.tar'
200 with tarfile.open(tar_path, 'w') as tar:
201 for f in files:
202 tar.add(valid_path() + f, arcname=f)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100203 with tarfile.open(tar_path, 'r') as tar:
204 fs_local.file_extract(tar, path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100205 extracted_path = valid_path() + (path if isinstance(path, str) else '/'.join(path))
206 ls_dir = os.listdir(extracted_path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100207 assert len(ls_dir) == len(files)
208 for f in files:
209 assert f in ls_dir
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100210 os.remove(tar_path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100211 for f in files:
212 os.remove(valid_path() + f)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100213 shutil.rmtree(extracted_path)
214
tiernob20a9022018-05-22 12:07:05 +0200215
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100216@pytest.mark.parametrize("storage, mode", [
217 (str(uuid.uuid4()), 'r'),
218 (str(uuid.uuid4()), 'w'),
219 (str(uuid.uuid4()), 'a'),
220 (str(uuid.uuid4()), 'rb'),
221 (str(uuid.uuid4()), 'wb'),
222 (str(uuid.uuid4()), 'ab'),
223 ([str(uuid.uuid4())], 'r'),
224 ([str(uuid.uuid4())], 'w'),
225 ([str(uuid.uuid4())], 'a'),
226 ([str(uuid.uuid4())], 'rb'),
227 ([str(uuid.uuid4())], 'wb'),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100228 ([str(uuid.uuid4())], 'ab')])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100229def test_file_open(fs_local, storage, mode):
230 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100231 os.mknod(path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100232 file_obj = fs_local.file_open(storage, mode)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100233 assert isinstance(file_obj, io.IOBase)
tiernob20a9022018-05-22 12:07:05 +0200234 assert file_obj.closed is False
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100235 os.remove(path)
236
tiernob20a9022018-05-22 12:07:05 +0200237
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100238@pytest.mark.parametrize("storage, mode", [
239 (str(uuid.uuid4()), 'r'),
240 (str(uuid.uuid4()), 'rb'),
241 ([str(uuid.uuid4())], 'r'),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100242 ([str(uuid.uuid4())], 'rb')])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100243def test_file_open_file_not_found_exception(fs_local, storage, mode):
244 with pytest.raises(FsException) as excinfo:
245 fs_local.file_open(storage, mode)
246 assert str(excinfo.value) == file_open_file_not_found_exception(storage)
247 assert excinfo.value.http_code == http.HTTPStatus.NOT_FOUND
248
tiernob20a9022018-05-22 12:07:05 +0200249
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100250@pytest.mark.parametrize("storage, mode", [
251 (str(uuid.uuid4()), 'r'),
252 (str(uuid.uuid4()), 'w'),
253 (str(uuid.uuid4()), 'a'),
254 (str(uuid.uuid4()), 'rb'),
255 (str(uuid.uuid4()), 'wb'),
256 (str(uuid.uuid4()), 'ab'),
257 ([str(uuid.uuid4())], 'r'),
258 ([str(uuid.uuid4())], 'w'),
259 ([str(uuid.uuid4())], 'a'),
260 ([str(uuid.uuid4())], 'rb'),
261 ([str(uuid.uuid4())], 'wb'),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100262 ([str(uuid.uuid4())], 'ab')])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100263def test_file_open_io_error(fs_local, storage, mode):
264 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100265 os.mknod(path)
266 os.chmod(path, 0)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100267 with pytest.raises(FsException) as excinfo:
268 fs_local.file_open(storage, mode)
269 assert str(excinfo.value) == file_open_io_exception(storage)
270 assert excinfo.value.http_code == http.HTTPStatus.BAD_REQUEST
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100271 os.remove(path)
272
tiernob20a9022018-05-22 12:07:05 +0200273
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100274@pytest.mark.parametrize("storage, with_files", [
275 (str(uuid.uuid4()), True),
276 (str(uuid.uuid4()), False),
277 ([str(uuid.uuid4())], True),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100278 ([str(uuid.uuid4())], False)])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100279def test_dir_ls(fs_local, storage, with_files):
280 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100281 os.mkdir(path)
tiernob20a9022018-05-22 12:07:05 +0200282 if with_files is True:
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100283 file_name = str(uuid.uuid4())
284 file_path = path + '/' + file_name
285 os.mknod(file_path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100286 result = fs_local.dir_ls(storage)
287
tiernob20a9022018-05-22 12:07:05 +0200288 if with_files is True:
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100289 assert len(result) == 1
290 assert result[0] == file_name
291 else:
292 assert len(result) == 0
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100293 shutil.rmtree(path)
294
tiernob20a9022018-05-22 12:07:05 +0200295
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100296@pytest.mark.parametrize("storage", [
297 (str(uuid.uuid4())),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100298 ([str(uuid.uuid4())])])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100299def test_dir_ls_with_not_a_directory_error(fs_local, storage):
300 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100301 os.mknod(path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100302 with pytest.raises(FsException) as excinfo:
303 fs_local.dir_ls(storage)
304 assert str(excinfo.value) == dir_ls_not_a_directory_exception(storage)
305 assert excinfo.value.http_code == http.HTTPStatus.NOT_FOUND
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100306 os.remove(path)
307
tiernob20a9022018-05-22 12:07:05 +0200308
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100309@pytest.mark.parametrize("storage", [
310 (str(uuid.uuid4())),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100311 ([str(uuid.uuid4())])])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100312def test_dir_ls_with_io_error(fs_local, storage):
313 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100314 os.mkdir(path)
315 os.chmod(path, 0)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100316 with pytest.raises(FsException) as excinfo:
317 fs_local.dir_ls(storage)
318 assert str(excinfo.value) == dir_ls_io_exception(storage)
319 assert excinfo.value.http_code == http.HTTPStatus.BAD_REQUEST
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100320 os.rmdir(path)
321
tiernob20a9022018-05-22 12:07:05 +0200322
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100323@pytest.mark.parametrize("storage, with_files, ignore_non_exist", [
324 (str(uuid.uuid4()), True, True),
325 (str(uuid.uuid4()), False, True),
326 (str(uuid.uuid4()), True, False),
327 (str(uuid.uuid4()), False, False),
328 ([str(uuid.uuid4())], True, True),
329 ([str(uuid.uuid4())], False, True),
330 ([str(uuid.uuid4())], True, False),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100331 ([str(uuid.uuid4())], False, False)])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100332def test_file_delete_with_dir(fs_local, storage, with_files, ignore_non_exist):
333 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100334 os.mkdir(path)
tiernob20a9022018-05-22 12:07:05 +0200335 if with_files is True:
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100336 file_path = path + '/' + str(uuid.uuid4())
337 os.mknod(file_path)
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100338 fs_local.file_delete(storage, ignore_non_exist)
tiernob20a9022018-05-22 12:07:05 +0200339 assert os.path.exists(path) is False
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100340
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100341
342@pytest.mark.parametrize("storage", [
343 (str(uuid.uuid4())),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100344 ([str(uuid.uuid4())])])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100345def test_file_delete_expect_exception(fs_local, storage):
346 with pytest.raises(FsException) as excinfo:
347 fs_local.file_delete(storage)
348 assert str(excinfo.value) == file_delete_exception_message(storage)
349 assert excinfo.value.http_code == http.HTTPStatus.NOT_FOUND
350
tiernob20a9022018-05-22 12:07:05 +0200351
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100352@pytest.mark.parametrize("storage", [
353 (str(uuid.uuid4())),
Eduardo Sousaacbbdf22018-05-03 15:47:41 +0100354 ([str(uuid.uuid4())])])
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100355def test_file_delete_no_exception(fs_local, storage):
356 path = valid_path() + storage if isinstance(storage, str) else valid_path() + storage[0]
Eduardo Sousaf5119a82018-04-25 17:55:17 +0100357 fs_local.file_delete(storage, ignore_non_exist=True)
tiernob20a9022018-05-22 12:07:05 +0200358 assert os.path.exists(path) is False