diff --git a/unittests/test_tool.py b/unittests/test_tool.py index fac8b60ac2d8f03322ba331c4d23e8ec69f9e1d4..7bdccbabdce2e71ddc8cf4d6c40ee033acba06b9 100755 --- a/unittests/test_tool.py +++ b/unittests/test_tool.py @@ -541,75 +541,132 @@ def test_replace_entities_with_ids(crawler): assert a.get_property("C").value == [12345, 233324] -@patch("caoscrawler.crawl.db.Container.insert") -@patch("caoscrawler.crawl.db.Container.update") -@patch("caoscrawler.crawl.UpdateCache.insert") -def test_security_mode_trivial(updateCacheMock, insmock, upmock, ident): - crawler = Crawler(debug=True, securityMode=SecurityMode.RETRIEVE) +def mock_get_entity_by_name(name): + candidates = [el for el in full_data.values() if el.name.lower() == name.lower()] + if len(candidates) > 0: + return candidates[0] + else: + return None + + +def prepare_crawler_with_sec_mode(mode, ident): + crawler = Crawler(debug=True, securityMode=mode) crawler.crawl_directory(rfp("test_directories", "examples_article"), rfp("scifolder_cfood.yml")) crawler.identifiableAdapter = ident - def mock_get_entity_by_name(name): - candidates = [el for el in full_data.values() if el.name.lower() == name.lower()] - if len(candidates) > 0: - return candidates[0] - else: - return None - Crawler._get_entity_by_name = mock_get_entity_by_name - #Crawler._get_entity_by_name = lambda x: db.RecordType(id=1111, name="A") - insl, updl = crawler.synchronize(commit_changes=True) - assert crawler.run_id is not None - insmock.assert_not_called() - upmock.update.assert_not_called() - updateCacheMock.assert_not_called() + return crawler + +def reset_mocks(mocks): + for mock in mocks: + mock.reset_mock() + +def change_identifiable_prop(ident): + # the checks in here are only to make sure we change the record as we intend to + meas = ident._records[-2] + assert meas.parents[0].name == "Measurement" + resps = meas.properties[0] + assert resps.name == "date" + # change one element; This changes the date which is part of the identifiable + resps.value = "2022-01-04" + + +def change_non_identifiable_prop(ident): + # the checks in here are only to make sure we change the record as we intend to + meas = ident._records[-1] + assert meas.parents[0].name == "Measurement" + resps = meas.properties[-1] + assert resps.name == "responsible" + assert len(resps.value) == 2 + # change one element; This removes a responsible which is not part of the identifiable + del resps.value[-1] + + +@patch("caoscrawler.crawl.Crawler._get_entity_by_name", + new=Mock(side_effect=mock_get_entity_by_name)) @patch("caoscrawler.crawl.db.Container.insert") @patch("caoscrawler.crawl.db.Container.update") @patch("caoscrawler.crawl.UpdateCache.insert") -def test_security_mode_forbidden(updateCacheMock, insmock, upmock, ident): - crawler = Crawler(debug=True, securityMode=SecurityMode.RETRIEVE) - crawler.crawl_directory(rfp("test_directories", "examples_article"), - rfp("scifolder_cfood.yml")) - crawler.identifiableAdapter = ident +def test_security_mode(updateCacheMock, upmock, insmock, ident): + records_backup = deepcopy(ident._records) - def mock_get_entity_by_name(name): - candidates = [el for el in full_data.values() if el.name.lower() == name.lower()] - if len(candidates) > 0: - return candidates[0] - else: - return None - Crawler._get_entity_by_name = mock_get_entity_by_name + # trivial case: nothing to do + crawler = prepare_crawler_with_sec_mode(SecurityMode.RETRIEVE, ident) + insl, updl = crawler.synchronize(commit_changes=True) + assert crawler.run_id is not None + insmock.assert_not_called() + upmock.assert_not_called() + updateCacheMock.assert_not_called() + + # RETRIEVE: insert only + crawler = prepare_crawler_with_sec_mode(SecurityMode.RETRIEVE, ident) + # remove one element del ident._records[-1] insl, updl = crawler.synchronize(commit_changes=True) assert crawler.run_id is not None insmock.assert_not_called() - upmock.update.assert_not_called() + upmock.assert_not_called() assert updateCacheMock.call_count == 1 - - -@patch("caoscrawler.crawl.db.Container.update") -@patch("caoscrawler.crawl.db.Container.insert") -@patch("caoscrawler.crawl.UpdateCache.insert") -def test_security_mode_forbidden_up(updateCacheMock, insmock, upmock, ident): - crawler = Crawler(debug=True, securityMode=SecurityMode.INSERT) - crawler.crawl_directory(rfp("test_directories", "examples_article"), - rfp("scifolder_cfood.yml")) - crawler.identifiableAdapter = ident - state = full_data - - def mock_get_entity_by_name(name): - candidates = [el for el in full_data.values() if el.name.lower() == name.lower()] - if len(candidates) > 0: - return candidates[0] - else: - return None - Crawler._get_entity_by_name = mock_get_entity_by_name - - del ident._registered_identifiables["Person"] + # reset counts + reset_mocks([updateCacheMock, insmock, upmock]) + # restore original ident + ident._records = deepcopy(records_backup) + + # RETRIEVE: update only + crawler = prepare_crawler_with_sec_mode(SecurityMode.RETRIEVE, ident) + # change one element + change_non_identifiable_prop(ident) insl, updl = crawler.synchronize(commit_changes=True) assert crawler.run_id is not None - insmock.assert_called_once() - upmock.update.assert_not_called() + insmock.assert_not_called() + upmock.assert_not_called() assert updateCacheMock.call_count == 1 + # reset counts + reset_mocks([updateCacheMock, insmock, upmock]) + # restore original ident + ident._records = deepcopy(records_backup) + + # INSERT: insert only + crawler = prepare_crawler_with_sec_mode(SecurityMode.INSERT, ident) + # remove one element + del ident._records[-1] + insl, updl = crawler.synchronize(commit_changes=True) + assert crawler.run_id is not None + insmock.assert_called_once() + upmock.assert_not_called() + updateCacheMock.assert_not_called() + # reset counts + reset_mocks([updateCacheMock, insmock, upmock]) + # restore original ident + ident._records = deepcopy(records_backup) + + # INSERT: update only + crawler = prepare_crawler_with_sec_mode(SecurityMode.INSERT, ident) + # change one element + change_non_identifiable_prop(ident) + insl, updl = crawler.synchronize(commit_changes=True) + assert crawler.run_id is not None + insmock.assert_not_called() + upmock.assert_not_called() + updateCacheMock.assert_called_once() + # reset counts + reset_mocks([updateCacheMock, insmock, upmock]) + # restore original ident + ident._records = deepcopy(records_backup) + + # INSERT: insert and update + crawler = prepare_crawler_with_sec_mode(SecurityMode.INSERT, ident) + # change two elements + change_non_identifiable_prop(ident) + change_identifiable_prop(ident) + insl, updl = crawler.synchronize(commit_changes=True) + assert crawler.run_id is not None + insmock.asser_called_once() + upmock.assert_not_called() + updateCacheMock.assert_called_once() + # reset counts + reset_mocks([updateCacheMock, insmock, upmock]) + # restore original ident + ident._records = deepcopy(records_backup)