2021-08-31 16:07:41 +00:00
|
|
|
from unittest import mock
|
2020-12-11 13:34:59 +00:00
|
|
|
from unittest.mock import patch
|
2021-08-31 16:07:41 +00:00
|
|
|
|
2021-01-08 19:42:13 +00:00
|
|
|
from tests.base_test import BaseTest
|
2020-12-11 13:34:59 +00:00
|
|
|
|
2020-12-11 16:41:32 +00:00
|
|
|
from crc import db
|
2020-12-14 15:27:40 +00:00
|
|
|
from crc.api.workflow_sync import get_all_spec_state, \
|
|
|
|
get_changed_workflows, \
|
|
|
|
get_workflow_spec_files, \
|
|
|
|
get_changed_files, \
|
|
|
|
get_workflow_specification, \
|
|
|
|
sync_changed_files
|
2020-12-11 16:41:32 +00:00
|
|
|
from crc.models.workflow import WorkflowSpecModel
|
|
|
|
from datetime import datetime
|
|
|
|
from crc.services.file_service import FileService
|
2021-08-31 16:07:41 +00:00
|
|
|
from crc.services.workflow_sync import WorkflowSyncService
|
2020-12-11 13:34:59 +00:00
|
|
|
|
2021-01-12 15:18:35 +00:00
|
|
|
def get_random_fact_pos(othersys):
|
|
|
|
"""
|
|
|
|
Make sure we get the 'random_fact' workflow spec
|
|
|
|
no matter what order it is in
|
|
|
|
"""
|
|
|
|
rf2pos = 0
|
|
|
|
for pos in range(len(othersys)):
|
|
|
|
if othersys[pos]['workflow_spec_id'] == 'random_fact':
|
|
|
|
rf2pos = pos
|
|
|
|
return rf2pos
|
|
|
|
|
|
|
|
|
|
|
|
def get_random_fact_2_pos(othersys):
|
|
|
|
"""
|
|
|
|
Makes sure we get the random_fact2.bpmn file no matter what order it is in
|
|
|
|
"""
|
|
|
|
rf2pos = 0
|
|
|
|
for pos in range(len(othersys)):
|
|
|
|
if othersys[pos]['filename'] == 'random_fact2.bpmn':
|
|
|
|
rf2pos = pos
|
|
|
|
return rf2pos
|
2020-12-14 15:27:40 +00:00
|
|
|
|
|
|
|
|
2020-12-11 13:34:59 +00:00
|
|
|
class TestWorkflowSync(BaseTest):
|
|
|
|
|
2020-12-11 16:41:32 +00:00
|
|
|
@patch('crc.services.workflow_sync.WorkflowSyncService.get_all_remote_workflows')
|
2020-12-11 13:34:59 +00:00
|
|
|
def test_get_no_changes(self, mock_get):
|
2020-12-11 16:41:32 +00:00
|
|
|
self.load_example_data()
|
2020-12-11 13:34:59 +00:00
|
|
|
othersys = get_all_spec_state()
|
2020-12-11 16:41:32 +00:00
|
|
|
mock_get.return_value = othersys
|
|
|
|
response = get_changed_workflows('localhost:0000') # not actually used due to mock
|
2020-12-11 13:34:59 +00:00
|
|
|
self.assertIsNotNone(response)
|
|
|
|
self.assertEqual(response,[])
|
|
|
|
|
2020-12-11 16:41:32 +00:00
|
|
|
|
|
|
|
@patch('crc.services.workflow_sync.WorkflowSyncService.get_all_remote_workflows')
|
|
|
|
def test_remote_workflow_change(self, mock_get):
|
|
|
|
self.load_example_data()
|
|
|
|
othersys = get_all_spec_state()
|
2021-01-12 15:18:35 +00:00
|
|
|
rf2pos = get_random_fact_pos(othersys)
|
2021-04-29 14:25:28 +00:00
|
|
|
othersys[rf2pos]['date_created'] = str(datetime.utcnow())
|
2021-01-12 15:18:35 +00:00
|
|
|
othersys[rf2pos]['md5_hash'] = '12345'
|
2020-12-11 16:41:32 +00:00
|
|
|
mock_get.return_value = othersys
|
|
|
|
response = get_changed_workflows('localhost:0000') #endpoint is not used due to mock
|
|
|
|
self.assertIsNotNone(response)
|
|
|
|
self.assertEqual(len(response),1)
|
|
|
|
self.assertEqual(response[0]['workflow_spec_id'], 'random_fact')
|
|
|
|
self.assertEqual(response[0]['location'], 'remote')
|
|
|
|
self.assertEqual(response[0]['new'], False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@patch('crc.services.workflow_sync.WorkflowSyncService.get_all_remote_workflows')
|
|
|
|
def test_remote_workflow_has_new(self, mock_get):
|
|
|
|
self.load_example_data()
|
|
|
|
othersys = get_all_spec_state()
|
|
|
|
othersys.append({'workflow_spec_id':'my_new_workflow',
|
2021-04-29 14:25:28 +00:00
|
|
|
'date_created':str(datetime.utcnow()),
|
2020-12-11 16:41:32 +00:00
|
|
|
'md5_hash': '12345'})
|
|
|
|
mock_get.return_value = othersys
|
|
|
|
response = get_changed_workflows('localhost:0000') #endpoint is not used due to mock
|
|
|
|
self.assertIsNotNone(response)
|
|
|
|
self.assertEqual(len(response),1)
|
|
|
|
self.assertEqual(response[0]['workflow_spec_id'],'my_new_workflow')
|
|
|
|
self.assertEqual(response[0]['location'], 'remote')
|
|
|
|
self.assertEqual(response[0]['new'], True)
|
|
|
|
|
|
|
|
|
|
|
|
@patch('crc.services.workflow_sync.WorkflowSyncService.get_all_remote_workflows')
|
|
|
|
def test_local_workflow_has_new(self, mock_get):
|
|
|
|
self.load_example_data()
|
|
|
|
|
|
|
|
othersys = get_all_spec_state()
|
|
|
|
mock_get.return_value = othersys
|
|
|
|
wf_spec = WorkflowSpecModel()
|
|
|
|
wf_spec.id = 'abcdefg'
|
|
|
|
wf_spec.display_name = 'New Workflow - Yum!!'
|
|
|
|
wf_spec.name = 'my_new_workflow'
|
|
|
|
wf_spec.description = 'yep - its a new workflow'
|
|
|
|
wf_spec.category_id = 0
|
|
|
|
wf_spec.display_order = 0
|
|
|
|
db.session.add(wf_spec)
|
|
|
|
db.session.commit()
|
|
|
|
FileService.add_workflow_spec_file(wf_spec,'dummyfile.txt','text',b'this is a test')
|
|
|
|
# after setting up the test - I realized that this doesn't return anything for
|
|
|
|
# a workflow that is new locally - it just returns nothing
|
|
|
|
response = get_changed_workflows('localhost:0000') #endpoint is not used due to mock
|
|
|
|
self.assertIsNotNone(response)
|
|
|
|
self.assertEqual(response,[])
|
2020-12-14 15:27:40 +00:00
|
|
|
|
|
|
|
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_workflow_spec_files')
|
2021-01-12 15:18:35 +00:00
|
|
|
def test_file_differences_clean_slate(self, mock_get):
|
|
|
|
""" This test is basically for coverage"""
|
2020-12-14 15:27:40 +00:00
|
|
|
self.load_example_data()
|
|
|
|
othersys = get_workflow_spec_files('random_fact')
|
|
|
|
mock_get.return_value = othersys
|
2021-01-12 15:18:35 +00:00
|
|
|
self.delete_example_data()
|
2020-12-14 15:27:40 +00:00
|
|
|
response = get_changed_files('localhost:0000','random_fact',as_df=False) #endpoint is not used due to mock
|
|
|
|
self.assertIsNotNone(response)
|
2021-01-12 15:18:35 +00:00
|
|
|
self.assertEqual(len(response),2)
|
2020-12-14 15:27:40 +00:00
|
|
|
self.assertEqual(response[0]['location'], 'remote')
|
2021-01-12 15:18:35 +00:00
|
|
|
self.assertEqual(response[0]['new'], True)
|
2020-12-14 15:27:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_workflow_spec_files')
|
|
|
|
def test_file_differences(self, mock_get):
|
|
|
|
self.load_example_data()
|
|
|
|
othersys = get_workflow_spec_files('random_fact')
|
2021-01-12 15:18:35 +00:00
|
|
|
rf2pos = get_random_fact_2_pos(othersys)
|
2021-04-29 14:25:28 +00:00
|
|
|
othersys[rf2pos]['date_created'] = str(datetime.utcnow())
|
2021-01-12 13:54:15 +00:00
|
|
|
othersys[rf2pos]['md5_hash'] = '12345'
|
2020-12-14 15:27:40 +00:00
|
|
|
mock_get.return_value = othersys
|
|
|
|
response = get_changed_files('localhost:0000','random_fact',as_df=False) #endpoint is not used due to mock
|
|
|
|
self.assertIsNotNone(response)
|
|
|
|
self.assertEqual(len(response),1)
|
|
|
|
self.assertEqual(response[0]['filename'], 'random_fact2.bpmn')
|
|
|
|
self.assertEqual(response[0]['location'], 'remote')
|
|
|
|
self.assertEqual(response[0]['new'], False)
|
|
|
|
|
|
|
|
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_file_by_hash')
|
|
|
|
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_workflow_spec_files')
|
|
|
|
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_workflow_spec')
|
2021-01-12 13:54:15 +00:00
|
|
|
def test_workflow_differences(self, workflow_mock, spec_files_mock, file_data_mock):
|
2020-12-14 15:27:40 +00:00
|
|
|
self.load_example_data()
|
2021-01-12 15:18:35 +00:00
|
|
|
# make a remote workflow that is slightly different from local
|
2020-12-14 15:27:40 +00:00
|
|
|
remote_workflow = get_workflow_specification('random_fact')
|
|
|
|
self.assertEqual(remote_workflow['display_name'],'Random Fact')
|
|
|
|
remote_workflow['description'] = 'This Workflow came from Remote'
|
|
|
|
remote_workflow['display_name'] = 'Remote Workflow'
|
2021-08-30 19:46:16 +00:00
|
|
|
remote_workflow['library'] = True
|
2020-12-14 15:27:40 +00:00
|
|
|
workflow_mock.return_value = remote_workflow
|
2021-01-12 15:18:35 +00:00
|
|
|
# change the remote file date and hash
|
2020-12-14 15:27:40 +00:00
|
|
|
othersys = get_workflow_spec_files('random_fact')
|
2021-01-12 15:18:35 +00:00
|
|
|
rf2pos = get_random_fact_2_pos(othersys)
|
2021-04-29 14:25:28 +00:00
|
|
|
othersys[rf2pos]['date_created'] = str(datetime.utcnow())
|
2021-01-12 13:54:15 +00:00
|
|
|
othersys[rf2pos]['md5_hash'] = '12345'
|
2020-12-14 15:27:40 +00:00
|
|
|
spec_files_mock.return_value = othersys
|
2021-01-12 15:18:35 +00:00
|
|
|
# actually go get a different file
|
2020-12-14 15:27:40 +00:00
|
|
|
file_data_mock.return_value = self.workflow_sync_response('random_fact2.bpmn')
|
|
|
|
response = sync_changed_files('localhost:0000','random_fact') # endpoint not used due to mock
|
2021-01-12 15:18:35 +00:00
|
|
|
# now make sure that everything gets pulled over
|
2020-12-14 15:27:40 +00:00
|
|
|
self.assertIsNotNone(response)
|
|
|
|
self.assertEqual(len(response),1)
|
|
|
|
self.assertEqual(response[0], 'random_fact2.bpmn')
|
|
|
|
files = FileService.get_spec_data_files('random_fact')
|
|
|
|
md5sums = [str(f.md5_hash) for f in files]
|
|
|
|
self.assertEqual('21bb6f9e-0af7-0ab2-0fc7-ec0f94787e58' in md5sums, True)
|
|
|
|
new_local_workflow = get_workflow_specification('random_fact')
|
|
|
|
self.assertEqual(new_local_workflow['display_name'],'Remote Workflow')
|
2021-08-30 19:46:16 +00:00
|
|
|
self.assertTrue(new_local_workflow['library'])
|
2020-12-14 15:27:40 +00:00
|
|
|
|
2021-08-31 16:07:41 +00:00
|
|
|
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_file_by_hash')
|
|
|
|
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_workflow_spec_files')
|
|
|
|
def test_workflow_sync_with_libraries(self, get_remote_workflow_spec_files_mock, get_remote_file_by_hash_mock):
|
|
|
|
self.load_example_data()
|
|
|
|
# make a remote workflow that is slightly different from local, and add a library to it.
|
|
|
|
remote_workflow = get_workflow_specification('random_fact')
|
|
|
|
remote_library = self.load_test_spec('two_forms')
|
|
|
|
remote_workflow['description'] = 'This Workflow came from Remote'
|
|
|
|
remote_workflow['libraries'] = [{'id': remote_library.id, 'name': 'two_forms', 'display_name': "Two Forms"}]
|
|
|
|
|
|
|
|
random_workflow_remote_files = get_workflow_spec_files('random_fact')
|
|
|
|
rf2pos = get_random_fact_2_pos(random_workflow_remote_files)
|
|
|
|
random_workflow_remote_files[rf2pos]['date_created'] = str(datetime.utcnow())
|
|
|
|
random_workflow_remote_files[rf2pos]['md5_hash'] = '12345'
|
|
|
|
get_remote_workflow_spec_files_mock.return_value = random_workflow_remote_files
|
|
|
|
get_remote_file_by_hash_mock.return_value = self.workflow_sync_response('random_fact2.bpmn')
|
|
|
|
|
|
|
|
# more mock stuff, but we need to return different things depending on what is asked, so we use the side
|
|
|
|
# effect pattern rather than setting a single return_value through a patch.
|
|
|
|
def mock_workflow_spec(*args):
|
|
|
|
if args[1] == 'random_fact':
|
|
|
|
return remote_workflow
|
|
|
|
else:
|
|
|
|
return get_workflow_specification(args[1])
|
|
|
|
|
|
|
|
with mock.patch.object(WorkflowSyncService, 'get_remote_workflow_spec', side_effect=mock_workflow_spec):
|
|
|
|
response = sync_changed_files('localhost:0000','random_fact') # endpoint not used due to mock
|
|
|
|
|
|
|
|
self.assertIsNotNone(response)
|
|
|
|
self.assertEqual(len(response),1)
|
|
|
|
self.assertEqual(response[0], 'random_fact2.bpmn')
|
|
|
|
files = FileService.get_spec_data_files('random_fact')
|
|
|
|
md5sums = [str(f.md5_hash) for f in files]
|
|
|
|
self.assertEqual('21bb6f9e-0af7-0ab2-0fc7-ec0f94787e58' in md5sums, True)
|
|
|
|
new_local_workflow = get_workflow_specification('random_fact')
|
|
|
|
self.assertEqual(new_local_workflow['display_name'],'Random Fact')
|
|
|
|
self.assertEqual(1, len(new_local_workflow['libraries']))
|
2020-12-14 15:27:40 +00:00
|
|
|
|
|
|
|
|
2021-01-12 15:18:35 +00:00
|
|
|
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_file_by_hash')
|
|
|
|
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_workflow_spec_files')
|
|
|
|
def test_ref_file_differences(self, spec_files_mock, file_data_mock):
|
|
|
|
"""
|
|
|
|
Make sure we copy over a new reference file if it exists
|
|
|
|
"""
|
|
|
|
self.load_example_data()
|
|
|
|
# make a remote workflow that is slightly different from local
|
|
|
|
othersys = get_workflow_spec_files('REFERENCE_FILES')
|
|
|
|
newfile = {'file_model_id':9999,
|
|
|
|
'workflow_spec_id': None,
|
|
|
|
'filename':'test.txt',
|
|
|
|
'type':'txt',
|
|
|
|
'primary':False,
|
|
|
|
'content_type':'text/text',
|
|
|
|
'primary_process_id':None,
|
2021-04-29 14:25:28 +00:00
|
|
|
'date_created':str(datetime.utcnow()),
|
2021-01-12 15:18:35 +00:00
|
|
|
'md5_hash':'12345'
|
|
|
|
}
|
|
|
|
othersys.append(newfile)
|
|
|
|
spec_files_mock.return_value = othersys
|
|
|
|
# actually go get a different file
|
|
|
|
file_data_mock.return_value = self.workflow_sync_response('test.txt')
|
|
|
|
response = sync_changed_files('localhost:0000','REFERENCE_FILES') # endpoint not used due to mock
|
|
|
|
# now make sure that everything gets pulled over
|
|
|
|
self.assertIsNotNone(response)
|
|
|
|
self.assertEqual(len(response),1)
|
|
|
|
self.assertEqual(response[0], 'test.txt')
|
|
|
|
ref_file = FileService.get_reference_file_data('test.txt')
|
|
|
|
self.assertEqual('24a2ab0d-1138-a80a-0b98-ed38894f5a04',str(ref_file.md5_hash))
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-12-14 15:27:40 +00:00
|
|
|
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_workflow_spec_files')
|
|
|
|
@patch('crc.services.workflow_sync.WorkflowSyncService.get_remote_workflow_spec')
|
|
|
|
def test_file_deleted(self, workflow_mock, spec_files_mock):
|
|
|
|
self.load_example_data()
|
|
|
|
remote_workflow = get_workflow_specification('random_fact')
|
|
|
|
workflow_mock.return_value = remote_workflow
|
|
|
|
othersys = get_workflow_spec_files('random_fact')
|
2021-01-12 15:18:35 +00:00
|
|
|
rf2pos = get_random_fact_2_pos(othersys)
|
|
|
|
del(othersys[rf2pos])
|
2020-12-14 15:27:40 +00:00
|
|
|
spec_files_mock.return_value = othersys
|
|
|
|
response = sync_changed_files('localhost:0000','random_fact') # endpoint not used due to mock
|
|
|
|
self.assertIsNotNone(response)
|
|
|
|
# when we delete a local file, we do not return that it was deleted - just
|
|
|
|
# a list of updated files. We may want to change this in the future.
|
|
|
|
self.assertEqual(len(response),0)
|
|
|
|
files = FileService.get_spec_data_files('random_fact')
|
|
|
|
self.assertEqual(len(files),1)
|
|
|
|
|