1 # Copyright 2019 Canonical
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
15 # For those usages not covered by the Apache License, Version 2.0 please
16 # contact: eduardo.sousa@canonical.com
23 from pymongo
import MongoClient
24 from gridfs
import GridFSBucket
26 from osm_common
.fsbase
import FsException
27 from osm_common
.fsmongo
import FsMongo
29 __author__
= "Eduardo Sousa <eduardo.sousa@canonical.com>"
33 return tempfile
.gettempdir() + '/'
40 @pytest.fixture(scope
="function", params
=[True, False])
41 def fs_mongo(request
, monkeypatch
):
42 def mock_mongoclient_constructor(a
, b
, c
):
45 def mock_mongoclient_getitem(a
, b
):
48 def mock_gridfs_constructor(a
, b
):
51 monkeypatch
.setattr(MongoClient
, '__init__', mock_mongoclient_constructor
)
52 monkeypatch
.setattr(MongoClient
, '__getitem__', mock_mongoclient_getitem
)
53 monkeypatch
.setattr(GridFSBucket
, '__init__', mock_gridfs_constructor
)
54 fs
= FsMongo(lock
=request
.param
)
59 'collection': 'files'})
63 def generic_fs_exception_message(message
):
64 return "storage exception {}".format(message
)
67 def fs_connect_exception_message(path
):
68 return "storage exception Invalid configuration param at '[storage]': path '{}' does not exist".format(path
)
71 def file_open_file_not_found_exception(storage
):
72 f
= storage
if isinstance(storage
, str) else '/'.join(storage
)
73 return "storage exception File {} does not exist".format(f
)
76 def file_open_io_exception(storage
):
77 f
= storage
if isinstance(storage
, str) else '/'.join(storage
)
78 return "storage exception File {} cannot be opened".format(f
)
81 def dir_ls_not_a_directory_exception(storage
):
82 f
= storage
if isinstance(storage
, str) else '/'.join(storage
)
83 return "storage exception File {} does not exist".format(f
)
86 def dir_ls_io_exception(storage
):
87 f
= storage
if isinstance(storage
, str) else '/'.join(storage
)
88 return "storage exception File {} cannot be opened".format(f
)
91 def file_delete_exception_message(storage
):
92 return "storage exception File {} does not exist".format(storage
)
95 def test_constructor_without_logger():
97 assert fs
.logger
== logging
.getLogger('fs')
98 assert fs
.path
is None
99 assert fs
.client
is None
103 def test_constructor_with_logger():
104 logger_name
= 'fs_mongo'
105 fs
= FsMongo(logger_name
=logger_name
)
106 assert fs
.logger
== logging
.getLogger(logger_name
)
107 assert fs
.path
is None
108 assert fs
.client
is None
112 def test_get_params(fs_mongo
, monkeypatch
):
113 def mock_gridfs_find(self
, search_query
, **kwargs
):
116 monkeypatch
.setattr(GridFSBucket
, 'find', mock_gridfs_find
)
117 params
= fs_mongo
.get_params()
118 assert len(params
) == 2
119 assert "fs" in params
120 assert "path" in params
121 assert params
["fs"] == "mongo"
122 assert params
["path"] == valid_path()
125 @pytest.mark
.parametrize("config, exp_logger, exp_path", [
128 'logger_name': 'fs_mongo',
129 'path': valid_path(),
130 'uri': 'mongo:27017',
131 'collection': 'files'
133 'fs_mongo', valid_path()
137 'logger_name': 'fs_mongo',
138 'path': valid_path(),
141 'collection': 'files'
143 'fs_mongo', valid_path()
147 'logger_name': 'fs_mongo',
148 'path': valid_path()[:-1],
149 'uri': 'mongo:27017',
150 'collection': 'files'
152 'fs_mongo', valid_path()
156 'logger_name': 'fs_mongo',
157 'path': valid_path()[:-1],
160 'collection': 'files'
162 'fs_mongo', valid_path()
166 'path': valid_path(),
167 'uri': 'mongo:27017',
168 'collection': 'files'
174 'path': valid_path(),
177 'collection': 'files'
183 'path': valid_path()[:-1],
184 'uri': 'mongo:27017',
185 'collection': 'files'
191 'path': valid_path()[:-1],
194 'collection': 'files'
198 def test_fs_connect_with_valid_config(config
, exp_logger
, exp_path
):
200 fs
.fs_connect(config
)
201 assert fs
.logger
== logging
.getLogger(exp_logger
)
202 assert fs
.path
== exp_path
203 assert type(fs
.client
) == MongoClient
204 assert type(fs
.fs
) == GridFSBucket
207 @pytest.mark
.parametrize("config, exp_exception_message", [
210 'logger_name': 'fs_mongo',
211 'path': invalid_path(),
212 'uri': 'mongo:27017',
213 'collection': 'files'
215 fs_connect_exception_message(invalid_path())
219 'logger_name': 'fs_mongo',
220 'path': invalid_path(),
223 'collection': 'files'
225 fs_connect_exception_message(invalid_path())
229 'logger_name': 'fs_mongo',
230 'path': invalid_path()[:-1],
231 'uri': 'mongo:27017',
232 'collection': 'files'
234 fs_connect_exception_message(invalid_path()[:-1])
238 'logger_name': 'fs_mongo',
239 'path': invalid_path()[:-1],
242 'collection': 'files'
244 fs_connect_exception_message(invalid_path()[:-1])
248 'path': invalid_path(),
249 'uri': 'mongo:27017',
250 'collection': 'files'
252 fs_connect_exception_message(invalid_path())
256 'path': invalid_path(),
259 'collection': 'files'
261 fs_connect_exception_message(invalid_path())
265 'path': invalid_path()[:-1],
266 'uri': 'mongo:27017',
267 'collection': 'files'
269 fs_connect_exception_message(invalid_path()[:-1])
273 'path': invalid_path()[:-1],
276 'collection': 'files'
278 fs_connect_exception_message(invalid_path()[:-1])
285 'collection': 'files'
287 generic_fs_exception_message(
288 "Invalid configuration param at '[storage]': path '/' is not writable"
291 def test_fs_connect_with_invalid_path(config
, exp_exception_message
):
293 with pytest
.raises(FsException
) as excinfo
:
294 fs
.fs_connect(config
)
295 assert str(excinfo
.value
) == exp_exception_message
298 @pytest.mark
.parametrize("config, exp_exception_message", [
301 'logger_name': 'fs_mongo',
302 'uri': 'mongo:27017',
303 'collection': 'files'
305 "Missing parameter \"path\""
309 'logger_name': 'fs_mongo',
312 'collection': 'files'
314 "Missing parameter \"path\""
318 'logger_name': 'fs_mongo',
319 'path': valid_path(),
320 'collection': 'files'
322 "Missing parameters: \"uri\" or \"host\" + \"port\""
326 'logger_name': 'fs_mongo',
327 'path': valid_path(),
329 'collection': 'files'
331 "Missing parameters: \"uri\" or \"host\" + \"port\""
335 'logger_name': 'fs_mongo',
336 'path': valid_path(),
338 'collection': 'files'
340 "Missing parameters: \"uri\" or \"host\" + \"port\""
344 'logger_name': 'fs_mongo',
345 'path': valid_path(),
348 "Missing parameter \"collection\""
352 'logger_name': 'fs_mongo',
353 'path': valid_path(),
357 "Missing parameter \"collection\""
359 def test_fs_connect_with_missing_parameters(config
, exp_exception_message
):
361 with pytest
.raises(FsException
) as excinfo
:
362 fs
.fs_connect(config
)
363 assert str(excinfo
.value
) == generic_fs_exception_message(exp_exception_message
)
366 @pytest.mark
.parametrize("config, exp_exception_message", [
369 'logger_name': 'fs_mongo',
370 'path': valid_path(),
371 'uri': 'mongo:27017',
372 'collection': 'files'
374 "MongoClient crashed"
378 'logger_name': 'fs_mongo',
379 'path': valid_path(),
382 'collection': 'files'
384 "MongoClient crashed"
386 def test_fs_connect_with_invalid_mongoclient(config
, exp_exception_message
, monkeypatch
):
387 def generate_exception(a
, b
, c
=None):
388 raise Exception(exp_exception_message
)
390 monkeypatch
.setattr(MongoClient
, '__init__', generate_exception
)
393 with pytest
.raises(FsException
) as excinfo
:
394 fs
.fs_connect(config
)
395 assert str(excinfo
.value
) == generic_fs_exception_message(exp_exception_message
)
398 @pytest.mark
.parametrize("config, exp_exception_message", [
401 'logger_name': 'fs_mongo',
402 'path': valid_path(),
403 'uri': 'mongo:27017',
404 'collection': 'files'
406 "Collection unavailable"
410 'logger_name': 'fs_mongo',
411 'path': valid_path(),
414 'collection': 'files'
416 "Collection unavailable"
418 def test_fs_connect_with_invalid_mongo_collection(config
, exp_exception_message
, monkeypatch
):
419 def mock_mongoclient_constructor(a
, b
, c
=None):
422 def generate_exception(a
, b
):
423 raise Exception(exp_exception_message
)
425 monkeypatch
.setattr(MongoClient
, '__init__', mock_mongoclient_constructor
)
426 monkeypatch
.setattr(MongoClient
, '__getitem__', generate_exception
)
429 with pytest
.raises(FsException
) as excinfo
:
430 fs
.fs_connect(config
)
431 assert str(excinfo
.value
) == generic_fs_exception_message(exp_exception_message
)
434 @pytest.mark
.parametrize("config, exp_exception_message", [
437 'logger_name': 'fs_mongo',
438 'path': valid_path(),
439 'uri': 'mongo:27017',
440 'collection': 'files'
442 "GridFsBucket crashed"
446 'logger_name': 'fs_mongo',
447 'path': valid_path(),
450 'collection': 'files'
452 "GridFsBucket crashed"
454 def test_fs_connect_with_invalid_gridfsbucket(config
, exp_exception_message
, monkeypatch
):
455 def mock_mongoclient_constructor(a
, b
, c
=None):
458 def mock_mongoclient_getitem(a
, b
):
461 def generate_exception(a
, b
):
462 raise Exception(exp_exception_message
)
464 monkeypatch
.setattr(MongoClient
, '__init__', mock_mongoclient_constructor
)
465 monkeypatch
.setattr(MongoClient
, '__getitem__', mock_mongoclient_getitem
)
466 monkeypatch
.setattr(GridFSBucket
, '__init__', generate_exception
)
469 with pytest
.raises(FsException
) as excinfo
:
470 fs
.fs_connect(config
)
471 assert str(excinfo
.value
) == generic_fs_exception_message(exp_exception_message
)
474 def test_fs_disconnect(fs_mongo
):
475 fs_mongo
.fs_disconnect()