class RepeaterFailureTest(BaseRepeaterTest): def setUp(self): super(RepeaterFailureTest, self).setUp() self.domain_name = "test-domain" self.domain = create_domain(self.domain_name) self.repeater = CaseRepeater( domain=self.domain_name, url='case-repeater-url', ) self.repeater.save() self.post_xml(self.xform_xml, self.domain_name) def tearDown(self): self.domain.delete() self.repeater.delete() delete_all_repeat_records() super(RepeaterFailureTest, self).tearDown() @run_with_all_backends def test_get_payload_exception(self): repeat_record = self.repeater.register( CaseAccessors(self.domain_name).get_case(CASE_ID)) with self.assertRaises(Exception): with patch.object(CaseRepeater, 'get_payload', side_effect=Exception('Boom!')): repeat_record.fire() self.assertEquals(repeat_record.failure_reason, 'Boom!') self.assertFalse(repeat_record.succeeded) @run_with_all_backends def test_failure(self): repeat_record = self.repeater.register( CaseAccessors(self.domain_name).get_case(CASE_ID)) with patch( 'corehq.apps.repeaters.models.simple_post_with_cached_timeout', side_effect=Exception('Boom!')): repeat_record.fire() self.assertEquals(repeat_record.failure_reason, 'Boom!') self.assertFalse(repeat_record.succeeded) # Should be marked as successful after a successful run with patch( 'corehq.apps.repeaters.models.simple_post_with_cached_timeout' ): repeat_record.fire() self.assertTrue(repeat_record.succeeded)
class RepeaterFailureTest(BaseRepeaterTest): def setUp(self): super(RepeaterFailureTest, self).setUp() self.domain_name = "test-domain" self.domain = create_domain(self.domain_name) self.repeater = CaseRepeater( domain=self.domain_name, url='case-repeater-url', ) self.repeater.save() self.post_xml(self.xform_xml, self.domain_name) def tearDown(self): self.domain.delete() self.repeater.delete() delete_all_repeat_records() super(RepeaterFailureTest, self).tearDown() @run_with_all_backends def test_failure(self): repeat_record = self.repeater.register(CaseAccessors(self.domain_name).get_case(CASE_ID)) with patch('corehq.apps.repeaters.models.simple_post_with_cached_timeout', side_effect=Exception('Boom!')): repeat_record.fire() self.assertEquals(repeat_record.failure_reason, 'Boom!') self.assertFalse(repeat_record.succeeded) # Should be marked as successful after a successful run with patch('corehq.apps.repeaters.models.simple_post_with_cached_timeout'): repeat_record.fire() self.assertTrue(repeat_record.succeeded)
class TestRepeaterFormat(BaseRepeaterTest): def setUp(self): self.domain = "test-domain" create_domain(self.domain) self.post_xml(xform_xml, self.domain) self.repeater = CaseRepeater( domain=self.domain, url='case-repeater-url', version=V1, format='new_format' ) self.repeater.save() def tearDown(self): self.repeater.delete() XFormInstance.get(instance_id).delete() repeat_records = RepeatRecord.all() for repeat_record in repeat_records: repeat_record.delete() def test_new_format_same_name(self): with self.assertRaises(DuplicateFormatException): @RegisterGenerator(CaseRepeater, 'case_xml', 'XML', is_default=False) class NewCaseGenerator(BasePayloadGenerator): def get_payload(self, repeat_record, payload_doc): return "some random case" def test_new_format_second_default(self): with self.assertRaises(DuplicateFormatException): @RegisterGenerator(CaseRepeater, 'rubbish', 'XML', is_default=True) class NewCaseGenerator(BasePayloadGenerator): def get_payload(self, repeat_record, payload_doc): return "some random case" def test_new_format_payload(self): payload = "some random case" @RegisterGenerator(CaseRepeater, 'new_format', 'XML') class NewCaseGenerator(BasePayloadGenerator): def get_payload(self, repeat_record, payload_doc): return payload repeat_record = self.repeater.register(CommCareCase.get(case_id)) with patch('corehq.apps.repeaters.models.simple_post_with_cached_timeout') as mock_post: repeat_record.fire() headers = self.repeater.get_headers(repeat_record) mock_post.assert_called_with( payload, self.repeater.url, headers=headers, force_send=False, timeout=POST_TIMEOUT, )
class RepeaterFailureTest(BaseRepeaterTest): def setUp(self): self.domain_name = "test-domain" self.domain = create_domain(self.domain_name) self.repeater = CaseRepeater( domain=self.domain_name, url='case-repeater-url', version=V1, format='other_format' ) self.repeater.save() self.post_xml(xform_xml, self.domain) def tearDown(self): self.domain.delete() self.repeater.delete() repeat_records = RepeatRecord.all() for repeat_record in repeat_records: repeat_record.delete() def test_failure(self): payload = "some random case" @RegisterGenerator(CaseRepeater, 'other_format', 'XML') class NewCaseGenerator(BasePayloadGenerator): def get_payload(self, repeat_record, payload_doc): return payload repeat_record = self.repeater.register(CommCareCase.get(case_id)) with patch('corehq.apps.repeaters.models.simple_post_with_cached_timeout', side_effect=Exception('Boom!')): repeat_record.fire() self.assertEquals(repeat_record.failure_reason, 'Boom!') self.assertFalse(repeat_record.succeeded) # Should be marked as successful after a successful run with patch('corehq.apps.repeaters.models.simple_post_with_cached_timeout'): repeat_record.fire() self.assertTrue(repeat_record.succeeded)
class RepeaterTest(BaseRepeaterTest): def setUp(self): super(RepeaterTest, self).setUp() self.domain = "test-domain" create_domain(self.domain) self.case_repeater = CaseRepeater( domain=self.domain, url='case-repeater-url', ) self.case_repeater.save() self.form_repeater = FormRepeater( domain=self.domain, url='form-repeater-url', ) self.form_repeater.save() self.log = [] self.post_xml(self.xform_xml, self.domain) def tearDown(self): self.case_repeater.delete() self.form_repeater.delete() FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) delete_all_repeat_records() super(RepeaterTest, self).tearDown() @run_with_all_backends def test_skip_device_logs(self): devicelog_xml = XFORM_XML_TEMPLATE.format(DEVICE_LOG_XMLNS, USER_ID, '1234', '') self.post_xml(devicelog_xml, self.domain) repeat_records = RepeatRecord.all(domain=self.domain) for repeat_record in repeat_records: self.assertNotEqual(repeat_record.payload_id, '1234') @run_with_all_backends def test_repeater_failed_sends(self): """ This tests records that fail are requeued later """ def now(): return datetime.utcnow() repeat_records = RepeatRecord.all(domain=self.domain, due_before=now()) self.assertEqual(len(repeat_records), 2) for repeat_record in repeat_records: with patch( 'corehq.apps.repeaters.models.simple_post', return_value=MockResponse(status_code=404, reason='Not Found')) as mock_post: repeat_record.fire() self.assertEqual(mock_post.call_count, 1) next_check_time = now() + timedelta(minutes=60) repeat_records = RepeatRecord.all( domain=self.domain, due_before=now() + timedelta(minutes=15), ) self.assertEqual(len(repeat_records), 0) repeat_records = RepeatRecord.all( domain=self.domain, due_before=next_check_time, ) self.assertEqual(len(repeat_records), 2) @run_with_all_backends def test_update_failure_next_check(self): now = datetime.utcnow() record = RepeatRecord(domain=self.domain, next_check=now) self.assertIsNone(record.last_checked) attempt = record.make_set_next_try_attempt(None) record.add_attempt(attempt) self.assertTrue(record.last_checked > now) self.assertEqual(record.next_check, record.last_checked + MIN_RETRY_WAIT) @run_with_all_backends def test_repeater_successful_send(self): repeat_records = RepeatRecord.all(domain=self.domain, due_before=datetime.utcnow()) for repeat_record in repeat_records: with patch( 'corehq.apps.repeaters.models.simple_post', return_value=MockResponse(status_code=200, reason='No Reason')) as mock_post: repeat_record.fire() self.assertEqual(mock_post.call_count, 1) mock_post.assert_any_call( repeat_record.get_payload(), repeat_record.repeater.get_url(repeat_record), headers=repeat_record.repeater.get_headers(repeat_record), timeout=POST_TIMEOUT, auth=repeat_record.repeater.get_auth(), ) # The following is pretty fickle and depends on which of # - corehq.apps.repeaters.signals # - casexml.apps.case.signals # gets loaded first. # This is deterministic but easily affected by minor code changes repeat_records = RepeatRecord.all( domain=self.domain, due_before=datetime.utcnow(), ) for repeat_record in repeat_records: self.assertEqual(repeat_record.succeeded, True) self.assertEqual(repeat_record.next_check, None) self.assertEqual(len(self.repeat_records(self.domain)), 0) self.post_xml(self.update_xform_xml, self.domain) self.assertEqual(len(self.repeat_records(self.domain)), 2) @run_with_all_backends def test_check_repeat_records(self): self.assertEqual(len(RepeatRecord.all()), 2) with patch('corehq.apps.repeaters.models.simple_post') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 2) with patch('corehq.apps.repeaters.models.simple_post') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 0) @run_with_all_backends def test_repeat_record_status_check(self): self.assertEqual(len(RepeatRecord.all()), 2) # Do not trigger cancelled records for repeat_record in RepeatRecord.all(): repeat_record.cancelled = True repeat_record.save() with patch('corehq.apps.repeaters.models.simple_post') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 0) # trigger force send records if not cancelled and tries not exhausted for repeat_record in RepeatRecord.all(): with patch('corehq.apps.repeaters.models.simple_post', return_value=MockResponse(status_code=200, reason='') ) as mock_fire: repeat_record.fire(force_send=True) self.assertEqual(mock_fire.call_count, 1) # all records should be in SUCCESS state after force try for repeat_record in RepeatRecord.all(): self.assertEqual(repeat_record.state, RECORD_SUCCESS_STATE) self.assertEqual(repeat_record.overall_tries, 1) # not trigger records succeeded triggered after cancellation with patch('corehq.apps.repeaters.models.simple_post') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 0) for repeat_record in RepeatRecord.all(): self.assertEqual(repeat_record.state, RECORD_SUCCESS_STATE) @run_with_all_backends def test_process_repeat_record_locking(self): self.assertEqual(len(RepeatRecord.all()), 2) with patch('corehq.apps.repeaters.tasks.process_repeat_record') as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 2) with patch('corehq.apps.repeaters.tasks.process_repeat_record') as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 0) records = RepeatRecord.all() # Saving should unlock them again by changing the rev for record in records: record.save() with patch('corehq.apps.repeaters.tasks.process_repeat_record') as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 2) @run_with_all_backends def test_automatic_cancel_repeat_record(self): repeat_record = self.case_repeater.register(CaseAccessors(self.domain).get_case(CASE_ID)) repeat_record.overall_tries = 1 with patch('corehq.apps.repeaters.models.simple_post', side_effect=Exception('Boom!')): repeat_record.fire() self.assertEqual(2, repeat_record.overall_tries) with patch('corehq.apps.repeaters.models.simple_post', side_effect=Exception('Boom!')): repeat_record.fire() self.assertEqual(True, repeat_record.cancelled) repeat_record.requeue() self.assertEqual(0, repeat_record.overall_tries) self.assertNotEqual(None, repeat_record.next_check)
class TestRepeaterFormat(BaseRepeaterTest): @classmethod def setUpClass(cls): super(TestRepeaterFormat, cls).setUpClass() cls.payload = 'some random case' @RegisterGenerator(CaseRepeater, 'new_format', 'XML') class NewCaseGenerator(BasePayloadGenerator): def get_payload(self, repeat_record, payload_doc): return cls.payload def setUp(self): super(TestRepeaterFormat, self).setUp() self.domain = "test-domain" create_domain(self.domain) self.post_xml(self.xform_xml, self.domain) self.repeater = CaseRepeater( domain=self.domain, url='case-repeater-url', format='new_format', ) self.repeater.save() def tearDown(self): self.repeater.delete() FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) delete_all_repeat_records() super(TestRepeaterFormat, self).tearDown() def test_new_format_same_name(self): with self.assertRaises(DuplicateFormatException): @RegisterGenerator(CaseRepeater, 'case_xml', 'XML', is_default=False) class NewCaseGenerator(BasePayloadGenerator): def get_payload(self, repeat_record, payload_doc): return self.payload def test_new_format_second_default(self): with self.assertRaises(DuplicateFormatException): @RegisterGenerator(CaseRepeater, 'rubbish', 'XML', is_default=True) class NewCaseGenerator(BasePayloadGenerator): def get_payload(self, repeat_record, payload_doc): return self.payload @run_with_all_backends def test_new_format_payload(self): repeat_record = self.repeater.register(CaseAccessors(self.domain).get_case(CASE_ID)) with patch('corehq.apps.repeaters.models.simple_post') as mock_post: repeat_record.fire() headers = self.repeater.get_headers(repeat_record) mock_post.assert_called_with( self.payload, self.repeater.url, headers=headers, timeout=POST_TIMEOUT, auth=self.repeater.get_auth(), )
class TestRepeaterFormat(BaseRepeaterTest): @classmethod def setUpClass(cls): super(TestRepeaterFormat, cls).setUpClass() cls.payload = 'some random case' @RegisterGenerator(CaseRepeater, 'new_format', 'XML') class NewCaseGenerator(BasePayloadGenerator): def get_payload(self, repeat_record, payload_doc): return cls.payload def setUp(self): super(TestRepeaterFormat, self).setUp() self.domain = "test-domain" create_domain(self.domain) self.post_xml(self.xform_xml, self.domain) self.repeater = CaseRepeater( domain=self.domain, url='case-repeater-url', format='new_format', ) self.repeater.save() def tearDown(self): self.repeater.delete() FormProcessorTestUtils.delete_all_xforms(self.domain) delete_all_repeat_records() super(TestRepeaterFormat, self).tearDown() def test_new_format_same_name(self): with self.assertRaises(DuplicateFormatException): @RegisterGenerator(CaseRepeater, 'case_xml', 'XML', is_default=False) class NewCaseGenerator(BasePayloadGenerator): def get_payload(self, repeat_record, payload_doc): return self.payload def test_new_format_second_default(self): with self.assertRaises(DuplicateFormatException): @RegisterGenerator(CaseRepeater, 'rubbish', 'XML', is_default=True) class NewCaseGenerator(BasePayloadGenerator): def get_payload(self, repeat_record, payload_doc): return self.payload @run_with_all_backends def test_new_format_payload(self): repeat_record = self.repeater.register(CaseAccessors(self.domain).get_case(CASE_ID)) with patch('corehq.apps.repeaters.models.simple_post_with_cached_timeout') as mock_post: repeat_record.fire() headers = self.repeater.get_headers(repeat_record) mock_post.assert_called_with( self.payload, self.repeater.url, headers=headers, force_send=False, timeout=POST_TIMEOUT, )