[715671f] | 1 | from unittest.mock import patch, Mock |
---|
| 2 | |
---|
| 3 | import pytest |
---|
| 4 | |
---|
| 5 | from ow.tasks.bulk import process_compressed_files |
---|
| 6 | |
---|
| 7 | |
---|
| 8 | class TestBulkTasks(object): |
---|
| 9 | |
---|
| 10 | @pytest.fixture |
---|
| 11 | def settings(self): |
---|
| 12 | settings = { |
---|
| 13 | 'workouts.bulk_tmp_path': '/tmp', |
---|
| 14 | 'workouts.bulk_loading_lock': '/tmp/queue-processor.lock'} |
---|
| 15 | return settings |
---|
| 16 | |
---|
| 17 | @pytest.fixture |
---|
| 18 | def root(self): |
---|
| 19 | root = { |
---|
| 20 | '_bulk_files': {} |
---|
| 21 | } |
---|
| 22 | return root |
---|
| 23 | |
---|
| 24 | @pytest.fixture |
---|
| 25 | def env(self, settings, root): |
---|
| 26 | env = { |
---|
| 27 | 'request': Mock(), |
---|
| 28 | 'root': root, |
---|
| 29 | 'registry': Mock(settings=settings) |
---|
| 30 | } |
---|
| 31 | return env |
---|
| 32 | |
---|
| 33 | @patch('fcntl.lockf') |
---|
| 34 | @patch('ow.tasks.bulk.log') |
---|
| 35 | def test_process_compressed_files_no_files(self, log, lockf, env): |
---|
| 36 | workouts_loaded = process_compressed_files(env) |
---|
| 37 | # the lockf was called, to set the lock on the lock file |
---|
| 38 | assert lockf.called |
---|
| 39 | # no warnings shown |
---|
| 40 | assert not log.warning.called |
---|
| 41 | # nothing loaded, no transaction committed |
---|
| 42 | assert not workouts_loaded |
---|
| 43 | assert not env['request'].tm.commit.called |
---|
| 44 | |
---|
| 45 | @patch('fcntl.lockf') |
---|
| 46 | @patch('ow.tasks.bulk.log') |
---|
| 47 | def test_process_compressed_files_single_file(self, log, lockf, env): |
---|
| 48 | bulk_file = Mock(loaded=False) |
---|
| 49 | env['root']['_bulk_files']['faked-bulk_id'] = bulk_file |
---|
| 50 | workouts_loaded = process_compressed_files(env) |
---|
| 51 | # the lockf was called, to set the lock on the lock file |
---|
| 52 | assert lockf.called |
---|
| 53 | # no warnings shown |
---|
| 54 | assert not log.warning.called |
---|
| 55 | # file loaded, transaction commited |
---|
| 56 | bulk_file.load.assert_called_once_with( |
---|
| 57 | env['root'], |
---|
| 58 | env['registry'].settings['workouts.bulk_tmp_path']) |
---|
| 59 | assert workouts_loaded |
---|
| 60 | env['request'].tm.commit.assert_called_once |
---|
| 61 | |
---|
| 62 | @patch('fcntl.lockf') |
---|
| 63 | @patch('ow.tasks.bulk.log') |
---|
| 64 | def test_process_compressed_files_already_loaded(self, log, lockf, env): |
---|
| 65 | bulk_file = Mock(loaded=True) |
---|
| 66 | env['root']['_bulk_files']['faked-bulk_id'] = bulk_file |
---|
| 67 | workouts_loaded = process_compressed_files(env) |
---|
| 68 | # the lockf was called, to set the lock on the lock file |
---|
| 69 | assert lockf.called |
---|
| 70 | # no warnings shown |
---|
| 71 | assert not log.warning.called |
---|
| 72 | # file already loaded, no transaction commited |
---|
| 73 | assert not bulk_file.load.called |
---|
| 74 | assert not workouts_loaded |
---|
| 75 | assert not env['request'].tm.commit.called |
---|
| 76 | |
---|
| 77 | @patch('fcntl.lockf') |
---|
| 78 | @patch('ow.tasks.bulk.log') |
---|
| 79 | def test_process_compressed_files_multiple_files(self, log, lockf, env): |
---|
| 80 | bulk_file = Mock(loaded=False) |
---|
| 81 | loaded_bulk_file = Mock(loaded=True) |
---|
| 82 | additional_bulk_file = Mock(loaded=False) |
---|
| 83 | env['root']['_bulk_files']['faked-bulk_id'] = bulk_file |
---|
| 84 | env['root']['_bulk_files']['loaded-bulk_id'] = loaded_bulk_file |
---|
| 85 | env['root']['_bulk_files']['additional-bulk_id'] = additional_bulk_file |
---|
| 86 | workouts_loaded = process_compressed_files(env) |
---|
| 87 | # the lockf was called, to set the lock on the lock file |
---|
| 88 | assert lockf.called |
---|
| 89 | # no warnings shown |
---|
| 90 | assert not log.warning.called |
---|
| 91 | # 2 files loaded, transaction commited once |
---|
| 92 | bulk_file.load.assert_called_once_with( |
---|
| 93 | env['root'], |
---|
| 94 | env['registry'].settings['workouts.bulk_tmp_path']) |
---|
| 95 | assert not loaded_bulk_file.load.called |
---|
| 96 | additional_bulk_file.load.assert_called_once_with( |
---|
| 97 | env['root'], |
---|
| 98 | env['registry'].settings['workouts.bulk_tmp_path']) |
---|
| 99 | assert workouts_loaded |
---|
| 100 | env['request'].tm.commit.assert_called_once |
---|
| 101 | |
---|
| 102 | @patch('fcntl.lockf') |
---|
| 103 | @patch('ow.tasks.bulk.log') |
---|
| 104 | def test_process_compressed_files_lock_ioerror(self, log, lockf, env): |
---|
| 105 | """ |
---|
| 106 | A second call to this task, while a first call is still running, |
---|
| 107 | does not do anything, just log a warning message to the logger |
---|
| 108 | """ |
---|
| 109 | # Make lock raise an IOError, mimicing what happens when the lock has |
---|
| 110 | # been acquired by another process |
---|
| 111 | e = IOError('could not lock file!') |
---|
| 112 | lockf.side_effect = e |
---|
| 113 | |
---|
| 114 | workouts_loaded = process_compressed_files(env) |
---|
| 115 | # Exception raised, False returned |
---|
| 116 | assert workouts_loaded is False |
---|
| 117 | |
---|
| 118 | # Calls: fcntl.lock has been called, then the IOError was raised |
---|
| 119 | # and no more calls to the api have been made |
---|
| 120 | assert lockf.called |
---|
| 121 | |
---|
| 122 | assert not log.info.called |
---|
| 123 | assert not log.error.called |
---|
| 124 | # except for the log call, which was a warning |
---|
| 125 | assert log.warning.called |
---|
| 126 | log_msg = log.warning.call_args_list[0][0][0] |
---|
| 127 | assert 'not run the workout bulk load task' in log_msg |
---|
| 128 | assert 'could not acquire lock' in log_msg |
---|