def test_resource_not_found_error(self, mock_sync_tenders):
     mock_sync_tenders.side_effect = [ResourceNotFound(), 'success']
     params = {'offset': 'offset', 'some_data': 'data'}
     mock_client = TestTendersClientSync()
     mock_client.session = mock.MagicMock()
     mock_client.session.cookies.clear = mock.Mock()
     response = get_response(mock_client, params)
     log_strings = self.log_capture_string.getvalue().split('\n')
     self.assertEqual(log_strings[0],
                      'Resource not found: Not described error yet.')
     self.assertEqual(mock_client.session.cookies.clear.call_count, 1)
     self.assertEqual(params, {'some_data': 'data'})
     self.assertEqual(response, 'success')
def test_check_lot(bot, logger, mocker):

    with open(ROOT + 'lots.json') as lots:
        lots = load(lots)

    lot = deepcopy(lots[0]['data'])
    wrong_status_lot = deepcopy(lot)
    wrong_status_lot['status'] = 'pending'

    mock_get_lot = mocker.MagicMock()
    mock_get_lot.side_effect = [
        RequestFailed(response=munchify({
            "text": "Request failed.",
            "status_code": 502
        })),
        ResourceNotFound(
            response=munchify({"text": "Lot could not be found."})),
        munchify({"data": lot}),
        munchify({"data": wrong_status_lot})
    ]

    bot.lots_client.get_lot = mock_get_lot

    result = bot.check_lot(lot)
    assert result is False

    result = bot.check_lot(lot)
    assert result is False

    result = bot.check_lot(lot)
    assert result is True

    result = bot.check_lot(wrong_status_lot)
    assert result is False

    log_strings = logger.log_capture_string.getvalue().split('\n')
    assert log_strings[
        0] == "Failed to get lot 9ee8f769438e403ebfb17b2240aedcf1. Status code: 502"
    assert log_strings[
        1] == "Failed to get lot 9ee8f769438e403ebfb17b2240aedcf1: Lot could not be found."
    assert log_strings[
        2] == "Successfully got lot 9ee8f769438e403ebfb17b2240aedcf1"
    assert log_strings[
        3] == "Successfully got lot 9ee8f769438e403ebfb17b2240aedcf1"
    assert log_strings[
        4] == "Lot 9ee8f769438e403ebfb17b2240aedcf1 can not be processed in current status ('pending')"
    def test_process_resource(self, mocked_logger, mocked_client):
        cache_db = AdaptiveCache({'0' * 32: datetime.now()})
        handler = AgreementObjectMaker(self.config, cache_db)

        # test no agreements
        resource = {'id': '0' * 32}
        handler.process_resource(resource)
        self.assertEquals(
            mocked_logger.warn.call_args_list,
            [
                call(
                    'No agreements found in tender {}'.format(resource['id']),
                    extra={'JOURNAL_TENDER_ID': resource['id'], 'MESSAGE_ID': 'missing_agreements'}
                )
            ]
        )

        # not active agreement
        resource['id'] = '1' * 32
        resource['dateModified'] = datetime.now()
        resource['agreements'] = [{'status': 'cancelled', 'id': '2' * 32}]
        handler.process_resource(resource)
        self.assertTrue(cache_db.has(resource['id']))

        # agreement exist in local db
        resource['id'] = '3' * 32
        resource['agreements'] = [{'status': 'active', 'id': '4' * 32}]
        cache_db.put('4' * 32, datetime.now())

        handler.process_resource(resource)

        self.assertEquals(
            mocked_logger.info.call_args_list[1:],
            [
                call(
                    'Agreement {} exist in local db'.format(resource['agreements'][0]['id'])
                )
            ]
        )
        self.assertTrue(cache_db.has(resource['id']))

        # not in local db
        resource['id'] = '5' * 32
        resource['agreements'] = [{'status': 'active', 'id': '6' * 32}]

        handler.process_resource(resource)

        handler.public_output_client.get_resource_item.assert_called_with(resource['agreements'][0]['id'])
        self.assertTrue(cache_db.has(resource['agreements'][0]['id']))
        self.assertEquals(cache_db[resource['agreements'][0]['id']], True)
        self.assertEquals(
            mocked_logger.info.call_args_list[2:],
            [
                call(
                    'Agreement {} already exist'.format(resource['agreements'][0]['id']),
                    extra={'JOURNAL_TENDER_ID': resource['id'], 'MESSAGE_ID': 'skip_agreement',
                           'JOURNAL_AGREEMENT_ID': resource['agreements'][0]['id']}
                )
            ]
        )

        # Resource not found, agreement should be created
        resource['id'] = '7' * 32
        resource['agreements'] = [{'status': 'active', 'id': '8' * 32}]
        e = ResourceNotFound()
        handler.public_output_client.get_resource_item = MagicMock(side_effect=e)
        handler.fill_agreement = MagicMock()
        handler.post_agreement = MagicMock()

        handler.process_resource(resource)

        self.assertTrue(cache_db.has(resource['id']))
        self.assertEquals(cache_db[resource['id']], resource['dateModified'])
        handler.fill_agreement.assert_called_with(munchify(resource['agreements'][0]), munchify(resource))
        handler.post_agreement.assert_called_with(munchify(resource['agreements'][0]))
        self.assertTrue(cache_db.has(resource['agreements'][0]['id']))
        self.assertEquals(
            mocked_logger.info.call_args_list[3:],
            [
                call(
                    'Sync agreement {} of tender {}'.format(resource['agreements'][0]['id'], resource['id']),
                    extra={'JOURNAL_TENDER_ID': resource['id'], 'MESSAGE_ID': 'got_agreement_for_sync',
                           'JOURNAL_AGREEMENT_ID': resource['agreements'][0]['id']}
                )
            ]
        )
        # Resource gone
        resource['id'] = '9' * 32
        resource['agreements'] = [{'status': 'active', 'id': '10' * 16}]
        e = ResourceGone()
        handler.public_output_client.get_resource_item = MagicMock(side_effect=e)

        handler.process_resource(resource)

        self.assertTrue(cache_db.has(resource['id']))
        self.assertEquals(cache_db[resource['id']], resource['dateModified'])
        self.assertEquals(
            mocked_logger.info.call_args_list[4:],
            [
                call(
                    'Sync agreement {} of tender {} has been archived'.format(resource['agreements'][0]['id'],
                                                                              resource['id']),
                    extra={'JOURNAL_TENDER_ID': resource['id'], 'MESSAGE_ID': 'skip_agreement',
                           'JOURNAL_AGREEMENT_ID': resource['agreements'][0]['id']}
                )
            ]
        )
def test_check_assets(bot, logger, mocker):
    with open(ROOT + 'assets.json') as assets:
        assets = load(assets)

    with open(ROOT + 'lots.json') as lots:
        lots = load(lots)

    verification_lot = deepcopy(lots[0]['data'])
    verification_lot['assets'] = ['e519404fd0b94305b3b19ec60add05e7']
    dissolved_lot = deepcopy(lots[1]['data'])
    dissolved_lot['assets'] = ["0a7eba27b22a454180d3a49b02a1842f"]

    mock_get_asset = mocker.MagicMock()
    mock_get_asset.side_effect = [
        RequestFailed(response=munchify({
            "text": "Request failed.",
            "status_code": 502
        })),
        ResourceNotFound(
            response=munchify({"text": "Asset could not be found."})),
        munchify(assets[0]),
        munchify(assets[7])
    ]

    bot.assets_client.get_asset = mock_get_asset

    with pytest.raises(RequestFailed):
        bot.check_assets(verification_lot)

    result = bot.check_assets(verification_lot)
    assert result is False

    result = bot.check_assets(verification_lot)
    assert result is True

    result = bot.check_assets(dissolved_lot)
    assert result is False

    verification_lot = deepcopy(lots[5]['data'])
    basic_asset = deepcopy(assets[7])
    basic_asset['data']['status'] = 'pending'
    basic_asset['data']['relatedLot'] = verification_lot['id']
    basic_asset['data']['assetType'] = 'basic'

    wrong_asset = deepcopy(assets[9])
    wrong_asset['data']['status'] = 'pending'
    wrong_asset['data']['assetType'] = 'wrong'
    wrong_asset['data']['relatedLot'] = verification_lot['id']

    mock_get_asset.side_effect = [munchify(wrong_asset), munchify(basic_asset)]

    verification_lot['assets'] = [wrong_asset['data']['id']]
    result = bot.check_assets(verification_lot)
    assert result is False

    verification_lot['assets'] = [basic_asset['data']['id']]
    result = bot.check_assets(verification_lot)
    assert result is True

    log_strings = logger.log_capture_string.getvalue().split('\n')
    assert log_strings[
        0] == "Failed to get asset e519404fd0b94305b3b19ec60add05e7. Status code: 502"
    assert log_strings[
        1] == "Failed to get asset e519404fd0b94305b3b19ec60add05e7: Asset could not be found."
    assert log_strings[
        2] == "Successfully got asset e519404fd0b94305b3b19ec60add05e7"
    assert log_strings[
        3] == "Successfully got asset 0a7eba27b22a454180d3a49b02a1842f"
    assert log_strings[4] == "Successfully got asset {}".format(
        wrong_asset['data']['id'])
    assert log_strings[5] == "Successfully got asset {}".format(
        basic_asset['data']['id'])
    def test_process_resource(self, mocked_logger, mocked_client, mocked_coordination):
        lock = MagicMock()

        coordinator = MagicMock()
        coordinator.get_lock.return_value = lock

        mocked_coordination.get_coordinator.return_value = coordinator
        cache_db = AdaptiveCache({'0' * 32: datetime.now()})
        handler = CFASelectionUAHandler(self.config, cache_db)

        # test lock _client exists
        resource = {'id': '0' * 32}
        handler.process_resource(resource)
        self.assertEquals(
            mocked_logger.info.call_args_list[1:],
            [
                call(
                    'Tender {} processing by another worker.'.format(resource['id']),
                    extra={'JOURNAL_TENDER_ID': resource['id'],
                           'MESSAGE_ID': 'tender_already_in_process'}
                )
            ]
        )

        # test actual process agreements
        agreement = {'data': {'id': '1' * 32, 'status': 'active'}}
        resource['agreements'] = [{'id': '1' * 32}]
        resource['status'] = 'active.enquires'
        resource['id'] = '10' * 16
        resource['dateModified'] = datetime.now()
        lock._client.exists.return_value = False
        handler.input_client.get_resource_item.return_value = agreement
        handler.output_client.patch_resource_item.return_value = {
            'data': {'status': resource['status']}
        }

        handler.process_resource(resource)
        self.assertEquals(
            mocked_logger.info.call_args_list[2:],
            [
                call(
                    'Received agreement data {}'.format(resource['agreements'][0]['id']),
                    extra={'JOURNAL_TENDER_ID': resource['id'],
                           'MESSAGE_ID': 'received_agreement_data',
                           'JOURNAL_AGREEMENT_ID': resource['agreements'][0]['id']}
                ),
                call(
                    'Patch tender agreement {}'.format(resource['agreements'][0]['id']),
                    extra={'JOURNAL_TENDER_ID': resource['id'],
                           'MESSAGE_ID': 'patch_agreement_data',
                           'JOURNAL_AGREEMENT_ID': resource['agreements'][0]['id']}
                ),
                call(
                    'Switch tender {} status to {}'.format(resource['id'], resource['status']),
                    extra={'JOURNAL_TENDER_ID': resource['id'],
                           'MESSAGE_ID': 'patch_tender_status'}
                ),
            ]
        )
        handler.input_client.get_resource_item.assert_called_with(resource['agreements'][0]['id'])

        handler.output_client.patch_resource_item_subitem.assert_called_with(
            resource['id'], agreement, 'agreements', subitem_id=resource['agreements'][0]['id']
        )
        handler.output_client.patch_resource_item(
            resource['id'], {'data': {'status': 'active.enquiries'}}
        )

        # test invalid/doesnt exist agreement
        resource = {'id': '8' * 32}
        resource['agreements'] = [{'id': '3' * 32}]
        resource['status'] = 'draft.unsuccessful'
        resource['dateModified'] = datetime.now()
        lock._client.exists.return_value = False
        e = ResourceNotFound()
        handler.input_client.get_resource_item = MagicMock()
        handler.input_client.get_resource_item.side_effect = (e, e, e, resource)
        handler.output_client.patch_resource_item.return_value = {
            'data': {'status': resource['status']}
        }

        handler.process_resource(resource)
        self.assertEquals(
            mocked_logger.info.call_args_list[5:],
            [
                call(
                    'Switch tender {} status to {}'.format(resource['id'], 'draft.unsuccessful'),
                    extra={'JOURNAL_TENDER_ID': resource['id'],
                           'MESSAGE_ID': 'patch_tender_status'}
                )
            ]
        )
        handler.output_client.patch_resource_item.called_with(resource['id'],
                                                              {'data': {'status': 'draft.unsuccessful'}})
        handler.input_client.get_resource_item.called_with(stop_max_attempt_number=3, wait_exponential_multiplier=1000)
        self.assertEqual(len(handler.input_client.get_resource_item.call_args_list), 3)

        # test the same tender and agreement '8' * 32 is already in cache
        resource = {'id': '8' * 32}
        resource['agreements'] = [{'id': '3' * 32}]
        resource['status'] = 'draft.unsuccessful'
        lock._client.exists.return_value = False
        e = ResourceNotFound()
        handler.input_client.get_resource_item = MagicMock()
        handler.input_client.get_resource_item.side_effect = (e, e, e, resource)
        handler.output_client.patch_resource_item.return_value = {
            'data': {'status': resource['status']}
        }

        handler.process_resource(resource)
        self.assertEquals(
            mocked_logger.info.call_args_list[6:],
            [
                call(
                    'Skipped tender {}'.format(resource['id']),
                    extra={'JOURNAL_TENDER_ID': resource['id'],
                           'MESSAGE_ID': 'SKIPPED'}
                )
            ]
        )