def after_scenario(_, scenario): if "clear_for_bad_messages" not in scenario.tags: response = requests.get(f'{Config.EXCEPTION_MANAGER_URL}/badmessages') response.raise_for_status() if response.json(): logger.error( 'Unexpected exception(s) -- these could be due to an underpowered environment', exception_manager_response=response.json()) requests.get(f'{Config.EXCEPTION_MANAGER_URL}/reset') time.sleep( 25 ) # 25 seconds should be long enough for error to happen again if it hasn't cleared itself response = requests.get( f'{Config.EXCEPTION_MANAGER_URL}/badmessages') response.raise_for_status() if response.json(): bad_message_details = [] list_of_bad_message_hashes = response.json() for bad_message_hash in list_of_bad_message_hashes: response = requests.get( f'{Config.EXCEPTION_MANAGER_URL}/badmessage/{bad_message_hash}' ) bad_message_details.append(response.json()) _clear_queues_for_bad_messages_and_reset_exception_manager() logger.error( 'Unexpected exception(s) which were not due to eventual consistency timing', exception_manager_response=bad_message_details) test_helper.fail( f'Unexpected exception(s) thrown by RM. Details: {bad_message_details}' )
def check_case_events(context): response = requests.get(f"{Config.CASE_API_CASE_URL}{context.first_case['id']}", params={'caseEvents': True}) response_json = response.json() for case_event in response_json['caseEvents']: if case_event['description'] == 'Invalid address': return test_helper.fail('Did not find expected invalid address event')
def check_for_event(context, event_type): events = get_logged_events_for_case_by_id(context.case_created_events[0]['payload']['collectionCase']['id']) for event in events: if event['eventType'] == event_type: return test_helper.fail(f"Case {context.first_case['id']} event_type {event_type} not logged")
def success_callback(db_result, timeout_deadline): if db_result[0][0] == context.sample_count: return True elif time.time() > timeout_deadline: test_helper.fail( f"For Action-plan {context.action_plan_id}, DB didn't have the expected number of sample units. " f"Expected: {context.sample_count}, actual: {db_result[0][0]}") return False
def check_question_linked_event_is_logged(case_id): response = requests.get(f'{Config.CASE_API_CASE_URL}{case_id}', params={'caseEvents': True}) response_json = response.json() for case_event in response_json['caseEvents']: if case_event['description'] == 'Questionnaire Linked': return test_helper.fail('Did not find questionnaire linked event')
def success_callback(db_result, timeout_deadline): results = {row[0]: row[1] for row in db_result} if all(results.values()) and len(results) == len(case_ids): return True elif time.time() > timeout_deadline: test_helper.fail( f"The expected cases did not all show as survey_launched=True within the time limit, " f"found values: {results}") return False
def check_case_events(context): response = requests.get( f'{Config.CASE_API_CASE_URL}{context.refused_case_id}', params={'caseEvents': True}) response_json = response.json() for case_event in response_json['caseEvents']: if case_event['description'] == 'Refusal Received': return test_helper.fail('Did not find "Refusal Received" event')
def check_case_events_logged(context): response = requests.get( f"{Config.CASE_API_CASE_URL}{context.fulfilment_requested_case_id}", params={'caseEvents': True}) response_json = response.json() for case_event in response_json['caseEvents']: if case_event['description'] == 'Fulfilment Request Received': return test_helper.fail('Did not find fulfilment request event')
def check_question_unlinked_event_is_logged(context): case_id = context.linked_case_id response = requests.get(f'{Config.CASE_API_CASE_URL}{case_id}', params={'caseEvents': True}) response_json = response.json() for case_event in response_json['caseEvents']: expected_desc = f'Questionnaire unlinked from case with QID {context.expected_questionnaire_id}' if case_event['description'] == expected_desc: return test_helper.fail('Questionnaire unlinked event has not occurred')
def receipt_msg_published_to_gcp_pubsub(context): context.first_case = context.case_created_events[0]['payload']['collectionCase'] for uac in context.uac_created_events: if uac['payload']['uac']['caseId'] == context.first_case['id']: questionnaire_id = uac['payload']['uac']['questionnaireId'] break else: test_helper.fail('Could not find UAC_UPDATED event for receipted case') _publish_object_finalize(context, questionnaire_id=questionnaire_id) test_helper.assertTrue(context.sent_to_gcp)
def _field_callback(ch, method, _properties, body, context): context.emitted_action_instruction = json.loads(body) if not context.emitted_action_instruction['actionInstruction'] == 'CREATE': ch.basic_nack(delivery_tag=method.delivery_tag) test_helper.fail( f'Unexpected message on {Config.RABBITMQ_OUTBOUND_FIELD_QUEUE} case queue. ' f'Got "{context.emitted_action_instruction["actionInstruction"]}", wanted "CREATE"' ) ch.basic_ack(delivery_tag=method.delivery_tag) ch.stop_consuming()
def _field_work_create_callback(ch, method, _properties, body, context): action_create = json.loads(body) if not action_create['actionInstruction'] == 'CREATE': ch.basic_nack(delivery_tag=method.delivery_tag) test_helper.fail(f'Unexpected message on {Config.RABBITMQ_OUTBOUND_FIELD_QUEUE} case queue. ' f'Got "{action_create["actionInstruction"]}", wanted "CREATE"') context.addressType = action_create['addressType'] context.fwmt_emitted_case_id = action_create['caseId'] context.field_action_create_message = action_create ch.basic_ack(delivery_tag=method.delivery_tag) ch.stop_consuming()
def _add_expected_uac_data(message, expected_data): case_id = message['payload']['uac']['caseId'] uac_payload = message['payload']['uac'] if uac_payload['questionnaireId'][:2] in ('01', '02', '04', '21', '22', '24'): expected_data[case_id]['uac'] = uac_payload['uac'] expected_data[case_id]['qid'] = uac_payload['questionnaireId'] elif uac_payload['questionnaireId'][:2] == '03': expected_data[case_id]['uac_wales'] = uac_payload['uac'] expected_data[case_id]['qid_wales'] = uac_payload['questionnaireId'] else: test_helper.fail('Unexpected questionnaire type') return expected_data
def field_work_update_callback(ch, method, _properties, body, context): action_instruction = json.loads(body) if not action_instruction['actionInstruction'] == 'UPDATE': ch.basic_nack(delivery_tag=method.delivery_tag) test_helper.fail( f'Unexpected message on {Config.RABBITMQ_OUTBOUND_FIELD_QUEUE} case queue. ' f'Got "{action_instruction["actionInstruction"]}", wanted "UPDATE"' ) for index, case in enumerate(context.expected_cases_for_action): if _message_matches(case, action_instruction): del context.expected_cases_for_action[index] ch.basic_ack(delivery_tag=method.delivery_tag) break
def test_uacs_correct(context): test_helper.assertEqual(len(context.messages_received), len(context.expected_uacs_cases)) for msg in context.uac_created_events: _validate_uac_message(msg) for index, case_created_event in enumerate( context.expected_uacs_cases): if (uac_message_matches_rh_message(case_created_event, msg) and (msg['payload']['uac']['questionnaireId'][:2] == case_created_event['expected_questionnaire_type'])): del context.expected_uacs_cases[index] break else: test_helper.fail('Could not find UAC Updated event')
def check_no_msgs_sent_to_queue(context, queue, on_message_callback, timeout=5): context.messages_received = [] rabbit = RabbitContext(queue_name=queue) connection = rabbit.open_connection() connection.call_later( delay=timeout, callback=functools.partial(_timeout_callback_expected, rabbit)) rabbit.channel.basic_consume( queue=queue, on_message_callback=on_message_callback) rabbit.channel.start_consuming() if len(context.messages_received) > 0: test_helper.fail(f'Expected no messages on the queue {queue}, found {len(context.messages_received)}' f', message(s): {context.messages_received}')
def new_address_load_success_callback(db_result, timeout_deadline): # Check we have the right number of cases and all the expected case ID's are present if len(db_result) == len(context.bulk_new_addresses): new_address_case_ids = { case_created['payload']['collectionCase']['id'] for case_created in context.case_created_events } for case_id in (result[0] for result in db_result): test_helper.assertIn( case_id, new_address_case_ids, f'Found case ID {case_id} in action plan {context.action_plan_id} ' f'with no matching created event from the new address bulk load' ) return True if time.time() > timeout_deadline: test_helper.fail( "Didn't find all new address cases in action database before the time out" ) return False
def get_ccs_case_by_postcode(context, case_type): response = requests.get( f'{Config.CASE_API_CASE_URL}ccs/postcode/{context.ccs_case["postcode"]}' ) response.raise_for_status() found_cases = response.json() for case in found_cases: if case['id'] == context.ccs_case['id']: matched_case = case break else: test_helper.fail('Failed to find the new CCS case by postcode search') test_helper.assertEqual(context.ccs_case['postcode'], matched_case['postcode']) test_helper.assertEqual(context.ccs_case['caseRef'], matched_case['caseRef']) test_helper.assertEqual(context.ccs_case['caseType'], case_type)
def _fieldwork_message_callback(ch, method, _properties, body, context, expected_value): action_instruction = json.loads(body) if not action_instruction['actionInstruction'] == 'CREATE': ch.basic_nack(delivery_tag=method.delivery_tag) test_helper.fail(f'Unexpected message on {Config.RABBITMQ_OUTBOUND_FIELD_QUEUE} case queue. ' f'Got "{action_instruction["actionInstruction"]}", wanted "CREATE"') for index, _ in enumerate(context.expected_cases_for_action): _check_expected_secure_establishment_value(action_instruction, expected_value) ch.basic_ack(delivery_tag=method.delivery_tag) del context.expected_cases_for_action[index] break else: test_helper.fail( f'Found message on {Config.RABBITMQ_OUTBOUND_FIELD_QUEUE} case queue which did not ' f'match any expected sample units') if not context.expected_cases_for_action: ch.stop_consuming()
def _test_cases_correct(context): context.expected_sample_units = context.sample_units.copy() test_helper.assertEqual( len(context.expected_sample_units), len(context.case_created_events), 'Number of cases loaded and case created events do not match') for event in context.case_created_events: _validate_case(event) for index, sample_unit in enumerate(context.expected_sample_units): if _sample_unit_matches_case_event(sample_unit, event): context.expected_sample_units.pop(index) break else: logger.error( 'To match case created event to any of the expected sample units', unmatched_sample_units=context.expected_sample_units, case_created_event=event) test_helper.fail( 'Could not find correct case updated messages for all loaded sample units' )
def _field_work_receipt_callback(ch, method, _properties, body, context): action_instruction = json.loads(body) if not action_instruction['actionInstruction'] == 'UPDATE': ch.basic_nack(delivery_tag=method.delivery_tag) test_helper.fail( f'Unexpected message on {Config.RABBITMQ_OUTBOUND_FIELD_QUEUE} case queue. ' f'Got "{action_instruction["actionInstruction"]}", wanted "UPDATE"' ) context.addressType = action_instruction['addressType'] context.fwmt_emitted_case_id = action_instruction['caseId'] context.fwmt_emitted_undelivered_flag = action_instruction[ 'undeliveredAsAddress'] test_helper.assertEquals(context.first_case['address']['uprn'], action_instruction['uprn'], "uprn") test_helper.assertEquals(context.first_case['address']['estabUprn'], action_instruction['estabUprn'], "estab Uprn") ch.basic_ack(delivery_tag=method.delivery_tag) ch.stop_consuming()
def success_callback(db_result, timeout_deadline): actual_event_types = [row[0] for row in db_result] if len(actual_event_types) > len(expected_event_types): # Fail fast if we find too many events test_helper.fail( f'Actual events logged against QID do not match expected, ' f'actual events: {actual_event_types}, expected: {expected_event_types}' ) if Counter(list(actual_event_types)) == Counter( list(expected_event_types)): # Counter returns a dict of list elements and their frequency in the given list so # comparing counters of lists will return true if they contain the same elements, ignoring order return True elif time.time() > timeout_deadline: test_helper.fail( f'Did not find expected QID events within the time limit, ' f'actual events: {actual_event_types}, expected: {expected_event_types}' ) return False
def validate_unaddressed_print_file(context): try: subprocess.run( ['docker', 'run', '--env', 'DB_HOST=postgres', '--env', 'DB_PORT=5432', '--env', 'OUR_PUBLIC_KEY_PATH=dummy_keys/our_dummy_public.asc', '--env', 'QM_PUBLIC_KEY_PATH=dummy_keys/supplier_QM_dummy_public_key.asc', '--env', 'PPO_PUBLIC_KEY_PATH=dummy_keys/supplier_PPO_dummy_public_key.asc', '--env', 'RABBITMQ_SERVICE_HOST=rabbitmq', '--env', 'RABBITMQ_SERVICE_PORT=5672', '--env', f'SFTP_QM_DIRECTORY={Config.SFTP_QM_DIRECTORY}', '--env', f'SFTP_PPO_DIRECTORY={Config.SFTP_PPO_DIRECTORY}', '--env', 'SFTP_HOST=sftp', '--env', 'SFTP_KEY_FILENAME=dummy_keys/dummy_rsa', '--env', 'SFTP_PASSPHRASE=secret', '--env', 'SFTP_USERNAME=centos', '--link', 'rabbitmq', '--link', 'postgres', '--network', 'censusrmdockerdev_default', '-t', 'eu.gcr.io/census-rm-ci/rm/census-rm-qid-batch-runner', '/home/qidbatchrunner/run_acceptance_tests.sh'], check=True) except subprocess.CalledProcessError: test_helper.fail('Unaddressed print file test failed')
def check_manifest_files_created(context, pack_code): with SftpUtility() as sftp_utility: files = sftp_utility.get_all_files_after_time( context.test_start_local_datetime, pack_code) for _file in files: if _file.filename.endswith(".csv.gpg"): csv_file = _file manifest_file = _get_matching_manifest_file( csv_file.filename, files) if manifest_file is None: test_helper.fail( f'Failed to find manifest file for {csv_file.filename}' ) actual_manifest = _get_actual_manifest(sftp_utility, manifest_file, pack_code) creation_datetime = actual_manifest['manifestCreated'] expected_manifest = _create_expected_manifest( sftp_utility, csv_file, creation_datetime, pack_code) test_helper.assertDictEqual(actual_manifest, expected_manifest)
ch.basic_nack(delivery_tag=method.delivery_tag) test_helper.fail( f'Unexpected message on {Config.RABBITMQ_OUTBOUND_FIELD_QUEUE} case queue. ' f'Got "{action_instruction["actionInstruction"]}", wanted "CREATE"' ) for index, case in enumerate(context.expected_cases_for_action): if _message_matches(case, action_instruction): _message_valid(case, action_instruction) del context.expected_cases_for_action[index] ch.basic_ack(delivery_tag=method.delivery_tag) break else: test_helper.fail( f'Found message on {Config.RABBITMQ_OUTBOUND_FIELD_QUEUE} case queue which did not ' f'match any expected sample units') if not context.expected_cases_for_action: ch.stop_consuming() def _message_matches(case, action_instruction): return action_instruction['caseId'] == case['id'] def _message_valid(case, action_instruction): test_helper.assertEqual(float(case['address']['latitude']), action_instruction['latitude']) test_helper.assertEqual(float(case['address']['longitude']), action_instruction['longitude'])
def create_expected_reminder_questionnaire_csv_lines(context, pack_code): expected_data = defaultdict(dict) expected_reminder_case_created_events = ( case for case in context.case_created_events if case['payload']['collectionCase']['id'] in context.reminder_case_ids ) for uac in context.reminder_uac_updated_events: if not uac['payload']['uac']['questionnaireId'].startswith('03'): expected_data[uac['payload']['uac'] ['caseId']]['uac'] = uac['payload']['uac']['uac'] expected_data[uac['payload']['uac']['caseId']]['qid'] = uac[ 'payload']['uac']['questionnaireId'] elif not expected_data[uac['payload']['uac']['caseId']].get( 'uac_wales'): expected_data[uac['payload']['uac']['caseId']]['uac_wales'] = uac[ 'payload']['uac']['uac'] expected_data[uac['payload']['uac']['caseId']]['qid_wales'] = uac[ 'payload']['uac']['questionnaireId'] else: test_helper.fail('Too many reminder UAC Updated events for case') for case in expected_reminder_case_created_events: expected_data = _add_expected_questionnaire_case_data( case, expected_data) return [ _create_expected_questionnaire_csv_line(case, pack_code) for case in expected_data.values() ] def _add_expected_uac_data(message, expected_data): case_id = message['payload']['uac']['caseId'] uac_payload = message['payload']['uac'] if uac_payload['questionnaireId'][:2] in ('01', '02', '04', '21', '22', '24'): expected_data[case_id]['uac'] = uac_payload['uac'] expected_data[case_id]['qid'] = uac_payload['questionnaireId'] elif uac_payload['questionnaireId'][:2] == '03': expected_data[case_id]['uac_wales'] = uac_payload['uac'] expected_data[case_id]['qid_wales'] = uac_payload['questionnaireId'] else: test_helper.fail('Unexpected questionnaire type') return expected_data def _add_expected_case_data(message, expected_data): case_id = message['payload']['collectionCase']['id'] collection_case = message['payload']['collectionCase'] expected_data[case_id]['case_ref'] = collection_case['caseRef'] expected_data[case_id]['coordinator_id'] = collection_case[ 'fieldCoordinatorId'] expected_data[case_id]['officer_id'] = collection_case['fieldOfficerId'] _populate_expected_address(case_id, expected_data, message) return expected_data def _add_expected_questionnaire_case_data(message, expected_data): case_id = message['payload']['collectionCase']['id'] expected_data[case_id]['coordinator_id'] = message['payload'][ 'collectionCase']['fieldCoordinatorId'] expected_data[case_id]['officer_id'] = message['payload'][ 'collectionCase']['fieldOfficerId'] _populate_expected_address(case_id, expected_data, message) return expected_data def _add_expected_individual_case_data(message, expected_data): case_id = message['payload']['collectionCase']['id'] collection_case = message['payload']['collectionCase'] expected_data[case_id]['case_ref'] = collection_case['caseRef'] _populate_expected_address(case_id, expected_data, message) return expected_data def _populate_expected_address(case_id, expected_data, message): address = message['payload']['collectionCase']['address'] expected_data[case_id]['address_line_1'] = address['addressLine1'] expected_data[case_id]['address_line_2'] = address['addressLine2'] expected_data[case_id]['address_line_3'] = address['addressLine3'] expected_data[case_id]['town_name'] = address['townName'] expected_data[case_id]['postcode'] = address['postcode'] expected_data[case_id]['organization_name'] = address['organisationName'] def _create_expected_csv_line(case, prefix): return (f'{case["uac"]}|' f'{case["case_ref"]}|' f'|||' f'{case["address_line_1"]}|' f'{case["address_line_2"]}|' f'{case["address_line_3"]}|' f'{case["town_name"]}|' f'{case["postcode"]}|' f'{prefix}|' f'{case["questionnaire_id"]}|' f'{case["organization_name"]}|' f'{case["coordinator_id"]}|' f'{case["officer_id"]}')
def _timeout_callback(rabbit): logger.error('Timed out waiting for messages') rabbit.close_connection() test_helper.fail("Didn't find the expected number of messages")