def setUp(self): super(SyncPerformanceTest, self).setUp() # the other user is an "owner" of the original users cases as well, # for convenience self.project = Domain(name='sync-performance-tests') self.other_user = User(user_id=OTHER_USER_ID, username=OTHER_USERNAME, password="******", date_joined=datetime(2011, 6, 9), additional_owner_ids=[SHARED_ID], domain=self.project.name) self.referral_user = User(user_id=REFERRAL_USER_ID, username=REFERRAL_USERNAME, password="******", date_joined=datetime(2011, 6, 9), additional_owner_ids=[REFERRED_TO_GROUP], domain=self.project.name) # this creates the initial blank sync token in the database self.other_sync_log = synclog_from_restore_payload(generate_restore_payload( self.project, self.other_user )) self.referral_sync_log = synclog_from_restore_payload(generate_restore_payload( self.project, self.referral_user )) self.assertTrue(SHARED_ID in self.other_sync_log.owner_ids_on_phone) self.assertTrue(OTHER_USER_ID in self.other_sync_log.owner_ids_on_phone) self.user.additional_owner_ids = [SHARED_ID] self.sync_log = synclog_from_restore_payload(generate_restore_payload( self.project, self.user )) self.assertTrue(SHARED_ID in self.sync_log.owner_ids_on_phone) self.assertTrue(USER_ID in self.sync_log.owner_ids_on_phone)
def testMismatch(self): self.assertEqual(CaseStateHash(EMPTY_HASH), self.sync_log.get_state_hash()) c1 = CaseBlock(case_id="abc123", create=True, owner_id=self.user.user_id).as_xml() c2 = CaseBlock(case_id="123abc", create=True, owner_id=self.user.user_id).as_xml() post_case_blocks([c1, c2], form_extras={"last_sync_token": self.sync_log.get_id}) self.sync_log = get_properly_wrapped_sync_log(self.sync_log.get_id) real_hash = CaseStateHash("409c5c597fa2c2a693b769f0d2ad432b") bad_hash = CaseStateHash("thisisntright") self.assertEqual(real_hash, self.sync_log.get_state_hash()) generate_restore_payload( self.project, self.user, self.sync_log.get_id, version=V2, state_hash=str(real_hash) ) try: generate_restore_payload(self.project, self.user, self.sync_log.get_id, version=V2, state_hash=str(bad_hash)) self.fail("Call to generate a payload with a bad hash should fail!") except BadStateException, e: self.assertEqual(real_hash, e.server_hash) self.assertEqual(bad_hash, e.phone_hash) self.assertEqual(2, len(e.case_ids)) self.assertTrue("abc123" in e.case_ids) self.assertTrue("123abc" in e.case_ids)
def test_selective_product_sync(self): user = bootstrap_user(self, phone_number="1234567890") expected_xml = self.generate_product_fixture_xml(user) product_list = Product.by_domain(user.domain) self._initialize_product_names(len(product_list)) fixture_original = product_fixture_generator(user, V1) generate_restore_payload(user.to_casexml_user()) self.assertXmlEqual( expected_xml, ElementTree.tostring(fixture_original[0]) ) first_sync = sorted(SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False ).all(), key=lambda x: x.date)[-1] # make sure the time stamp on this first sync is # not on the same second that the products were created first_sync.date += datetime.timedelta(seconds=1) # second sync is before any changes are made, so there should # be no products synced fixture_pre_change = product_fixture_generator(user, V1, last_sync=first_sync) generate_restore_payload(user.to_casexml_user()) self.assertEqual( [], fixture_pre_change, "Fixture was not empty on second sync" ) second_sync = sorted(SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False ).all(), key=lambda x: x.date)[-1] self.assertTrue(first_sync._id != second_sync._id) # save should make the product more recently updated than the # last sync for product in product_list: product.save() # now that we've updated a product, we should get # product data in sync again fixture_post_change = product_fixture_generator(user, V1, last_sync=second_sync) # regenerate the fixture xml to make sure it is still legit self.assertXmlEqual( expected_xml, ElementTree.tostring(fixture_post_change[0]) )
def setUp(self): delete_all_cases() delete_all_xforms() delete_all_sync_logs() self.project = Domain(name='state-hash-tests-project') self.user = User(user_id="state_hash", username="******", password="******", date_joined=datetime(2011, 6, 9)) # this creates the initial blank sync token in the database generate_restore_payload(self.project, self.user) self.sync_log = get_exactly_one_wrapped_sync_log()
def setUp(self): delete_all_cases() delete_all_xforms() delete_all_sync_logs() self.user = User(user_id="state_hash", username="******", password="******", date_joined=datetime(2011, 6, 9)) # this creates the initial blank sync token in the database generate_restore_payload(self.user) [sync_log] = SyncLog.view("phone/sync_logs_by_user", include_docs=True, reduce=False).all() self.sync_log = sync_log
def setUp(self): delete_all_cases() delete_all_xforms() delete_all_sync_logs() delete_all_users() self.project = Domain(name='state-hash-tests-project') self.project.save() self.user = create_restore_user(domain=self.project.name) # this creates the initial blank sync token in the database generate_restore_payload(self.project, self.user) self.sync_log = get_exactly_one_wrapped_sync_log()
def testOverwriteCache(self): restore_payload = generate_restore_payload( self.project, dummy_user(), items=True, force_cache=True ) restore_payload_cached = generate_restore_payload( self.project, dummy_user(), items=True ) restore_payload_overwrite = generate_restore_payload( self.project, dummy_user(), items=True, overwrite_cache=True ) self.assertEqual(restore_payload, restore_payload_cached) self.assertNotEqual(restore_payload, restore_payload_overwrite)
def setUp(self): super(SyncPerformanceTest, self).setUp() # the other user is an "owner" of the original users cases as well, # for convenience self.project = Domain(name='sync-performance-tests') self.project.save() self.factory.domain = self.project.name self.other_user = create_restore_user( domain=self.project.name, username=OTHER_USERNAME, ) self.referral_user = create_restore_user( domain=self.project.name, username=REFERRAL_USERNAME, ) self.shared_group = Group( domain=self.project.name, name='shared_group', case_sharing=True, users=[self.other_user.user_id, self.user.user_id] ) self.shared_group.save() self.referral_group = Group( domain=self.project.name, name='referral_group', case_sharing=True, users=[self.referral_user.user_id] ) self.referral_group.save() # this creates the initial blank sync token in the database self.other_sync_log = synclog_from_restore_payload(generate_restore_payload( self.project, self.other_user )) self.referral_sync_log = synclog_from_restore_payload(generate_restore_payload( self.project, self.referral_user )) self.assertTrue(self.shared_group._id in self.other_sync_log.owner_ids_on_phone) self.assertTrue(self.other_user.user_id in self.other_sync_log.owner_ids_on_phone) self.sync_log = synclog_from_restore_payload(generate_restore_payload( self.project, self.user )) self.assertTrue(self.shared_group._id in self.sync_log.owner_ids_on_phone) self.assertTrue(self.user.user_id in self.sync_log.owner_ids_on_phone)
def testEmpty(self): empty_hash = CaseStateHash(EMPTY_HASH) wrong_hash = CaseStateHash("thisisntright") self.assertEqual(empty_hash, self.sync_log.get_state_hash()) response = generate_restore_response(self.user, self.sync_log.get_id, version=V2) self.assertEqual(200, response.status_code) try: generate_restore_payload(self.user, self.sync_log.get_id, version=V2, state_hash=str(wrong_hash)) self.fail("Call to generate a payload with a bad hash should fail!") except BadStateException, e: self.assertEqual(empty_hash, e.expected) self.assertEqual(wrong_hash, e.actual) self.assertEqual(0, len(e.case_ids))
def testUserRestoreWithCase(self): file_path = os.path.join(os.path.dirname(__file__), "data", "create_short.xml") with open(file_path, "rb") as f: xml_data = f.read() # implicit length assertion _, _, [newcase] = submit_form_locally(xml_data, domain=self.project.name) expected_case_block = """ <case> <case_id>asdf</case_id> <date_modified>2010-06-29T13:42:50.000000Z</date_modified> <create> <case_type_id>test_case_type</case_type_id> <user_id>foo</user_id> <case_name>test case name</case_name> <external_id>someexternal</external_id> </create> </case>""" check_xml_line_by_line(self, expected_case_block, xml.get_case_xml(newcase, [case_const.CASE_ACTION_CREATE, case_const.CASE_ACTION_UPDATE])) # check v2 expected_v2_case_block = """ <case case_id="asdf" date_modified="2010-06-29T13:42:50.000000Z" user_id="foo" xmlns="http://commcarehq.org/case/transaction/v2" > <create> <case_type>test_case_type</case_type> <case_name>test case name</case_name> <owner_id>foo</owner_id> </create> <update> <external_id>someexternal</external_id> </update> </case>""" check_xml_line_by_line( self, expected_v2_case_block, xml.get_case_xml( newcase, [case_const.CASE_ACTION_CREATE, case_const.CASE_ACTION_UPDATE], version="2.0", ), ) restore_payload = generate_restore_payload( project=self.project, user=dummy_user(), items=True, ) sync_log_id = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).one().get_id check_xml_line_by_line( self, dummy_restore_xml(sync_log_id, expected_case_block, items=4), restore_payload )
def testUserRestoreWithCase(self): file_path = os.path.join(os.path.dirname(__file__), "data", "create_short.xml") with open(file_path, "rb") as f: xml_data = f.read() FormProcessorInterface.submit_form_locally(xml_data, self.domain) expected_case_block = """ <case case_id="asdf" date_modified="2010-06-29T13:42:50.000000Z" user_id="foo" xmlns="http://commcarehq.org/case/transaction/v2"> <create> <case_type>test_case_type</case_type> <case_name>test case name</case_name> <owner_id>foo</owner_id> </create> <update> <external_id>someexternal</external_id> </update> </case>""" restore_payload = generate_restore_payload( project=Domain(name=self.domain), user=dummy_user(), items=True, version=V3 ) sync_log_id = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).one().get_id check_xml_line_by_line( self, dummy_restore_xml(sync_log_id, expected_case_block, items=4), restore_payload )
def test_selective_program_sync(self): user = create_restore_user(self.domain.name) Program(domain=user.domain, name="test1", code="t1").save() program_list = Program.by_domain(user.domain) program_xml = self.generate_program_xml(program_list, user) fixture_original = program_fixture_generator(user, V1) generate_restore_payload(self.domain, user) self.assertXmlEqual(program_xml, ElementTree.tostring(fixture_original[0])) first_sync = sorted( SyncLog.view("phone/sync_logs_by_user", include_docs=True, reduce=False).all(), key=lambda x: x.date )[-1] # make sure the time stamp on this first sync is # not on the same second that the programs were created first_sync.date += datetime.timedelta(seconds=1) # second sync is before any changes are made, so there should # be no programs synced fixture_pre_change = program_fixture_generator(user, V1, last_sync=first_sync) generate_restore_payload(self.domain, user) self.assertEqual([], fixture_pre_change, "Fixture was not empty on second sync") second_sync = sorted( SyncLog.view("phone/sync_logs_by_user", include_docs=True, reduce=False).all(), key=lambda x: x.date )[-1] self.assertTrue(first_sync._id != second_sync._id) # save should make the program more recently updated than the # last sync for program in program_list: program.save() # now that we've updated a program, we should get # program data in sync again fixture_post_change = program_fixture_generator(user, V1, last_sync=second_sync) # regenerate the fixture xml to make sure it is still legit self.assertXmlEqual(program_xml, ElementTree.tostring(fixture_post_change[0]))
def setUp(self): super(MultiUserSyncTest, self).setUp() # the other user is an "owner" of the original users cases as well, # for convenience self.other_user = User(user_id=OTHER_USER_ID, username=OTHER_USERNAME, password="******", date_joined=datetime(2011, 6, 9), additional_owner_ids=[SHARED_ID]) # this creates the initial blank sync token in the database self.other_sync_log = synclog_from_restore_payload( generate_restore_payload(self.other_user) ) self.assertTrue(SHARED_ID in self.other_sync_log.owner_ids_on_phone) self.assertTrue(OTHER_USER_ID in self.other_sync_log.owner_ids_on_phone) self.user.additional_owner_ids = [SHARED_ID] self.sync_log = synclog_from_restore_payload( generate_restore_payload(self.user) ) self.assertTrue(SHARED_ID in self.sync_log.owner_ids_on_phone) self.assertTrue(USER_ID in self.sync_log.owner_ids_on_phone)
def testComplicatedGatesBug(self): # found this bug in the wild, used the real (test) forms to fix it # just running through this test used to fail hard, even though there # are no asserts self.assertEqual(0, len(CommCareCase.view("case/by_user", reduce=False).all())) folder_path = os.path.join("bugs", "dependent_case_conflicts") files = ["reg1.xml", "reg2.xml", "cf.xml", "close.xml"] for f in files: form = self._postWithSyncToken(os.path.join(folder_path, f), self.sync_log.get_id) form = XFormInstance.get(form.get_id) self.assertFalse(hasattr(form, "problem")) self.sync_log = synclog_from_restore_payload( generate_restore_payload(self.user, version="2.0") )
def testUserRestore(self): self.assertEqual(0, SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).count()) restore_payload = generate_restore_payload(self.project, dummy_user(), items=True) sync_log = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).one() check_xml_line_by_line( self, dummy_restore_xml(sync_log.get_id, items=3), restore_payload, )
def testRestoreAttributes(self): xml_data = self.get_xml('attributes') xml_data = xml_data.format(user_id=self.restore_user.user_id) newcase = submit_form_locally(xml_data, domain=self.project.name).case self.assertTrue(isinstance(newcase.adate, dict)) self.assertEqual(date(2012, 02, 01), newcase.adate["#text"]) self.assertEqual("i am an attribute", newcase.adate["@someattr"]) self.assertTrue(isinstance(newcase.dateattr, dict)) self.assertEqual("this shouldn't break", newcase.dateattr["#text"]) self.assertEqual(date(2012, 01, 01), newcase.dateattr["@somedate"]) self.assertTrue(isinstance(newcase.stringattr, dict)) self.assertEqual("neither should this", newcase.stringattr["#text"]) self.assertEqual("i am a string", newcase.stringattr["@somestring"]) restore_payload = generate_restore_payload(self.project, self.restore_user) # ghetto self.assertTrue('<dateattr somedate="2012-01-01">' in restore_payload) self.assertTrue( '<stringattr somestring="i am a string">' in restore_payload)
def test_user_restore(self): from casexml.apps.phone.tests.utils import generate_restore_payload from casexml.apps.case.xml import V3 from corehq.apps.userreports.reports.data_source import ConfigurableReportDataSource with patch.object(ConfigurableReportDataSource, 'get_data') as get_data_mock: get_data_mock.return_value = self.rows with mock_sql_backend(): with mock_datasource_config(): restore = generate_restore_payload(self.domain_obj, self.user, version=V3) self.assertIn('<fixture id="commcare:reports"', restore) self.assertIn( 'report_id="{id}"'.format(id=self.report_config1._id), restore) self.assertIn( 'report_id="{id}"'.format(id=self.report_config2._id), restore)
def testRestoreAttributes(self): file_path = os.path.join(os.path.dirname(__file__), "data", "attributes.xml") with open(file_path, "rb") as f: xml_data = f.read() _, _, [newcase] = FormProcessorInterface.submit_form_locally(xml_data, domain=self.project.name) self.assertTrue(isinstance(newcase.adate, dict)) self.assertEqual(date(2012, 02, 01), newcase.adate["#text"]) self.assertEqual("i am an attribute", newcase.adate["@someattr"]) self.assertTrue(isinstance(newcase.dateattr, dict)) self.assertEqual("this shouldn't break", newcase.dateattr["#text"]) self.assertEqual(date(2012, 01, 01), newcase.dateattr["@somedate"]) self.assertTrue(isinstance(newcase.stringattr, dict)) self.assertEqual("neither should this", newcase.stringattr["#text"]) self.assertEqual("i am a string", newcase.stringattr["@somestring"]) restore_payload = generate_restore_payload(self.project, dummy_user()) # ghetto self.assertTrue('<dateattr somedate="2012-01-01">' in restore_payload) self.assertTrue('<stringattr somestring="i am a string">' in restore_payload)
def testRestoreAttributes(self): file_path = os.path.join(os.path.dirname(__file__), "data", "attributes.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data, domain=self.project.name) [newcase] = process_cases(form) self.assertTrue(isinstance(newcase.adate, dict)) self.assertEqual(date(2012,02,01), newcase.adate["#text"]) self.assertEqual("i am an attribute", newcase.adate["@someattr"]) self.assertTrue(isinstance(newcase.dateattr, dict)) self.assertEqual("this shouldn't break", newcase.dateattr["#text"]) self.assertEqual(date(2012,01,01), newcase.dateattr["@somedate"]) self.assertTrue(isinstance(newcase.stringattr, dict)) self.assertEqual("neither should this", newcase.stringattr["#text"]) self.assertEqual("i am a string", newcase.stringattr["@somestring"]) restore_payload = generate_restore_payload(self.project, dummy_user()) # ghetto self.assertTrue('<dateattr somedate="2012-01-01">' in restore_payload) self.assertTrue('<stringattr somestring="i am a string">' in restore_payload)
def testUserRestore(self): self.assertEqual( 0, SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).count()) restore_payload = generate_restore_payload(self.project, self.restore_user, items=True) sync_log = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).one() check_xml_line_by_line( self, dummy_restore_xml(sync_log.get_id, items=3, user=self.restore_user), restore_payload, )
def testRestoreAttributes(self): file_path = os.path.join(os.path.dirname(__file__), "data", "attributes.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) [newcase] = CommCareCase.view("case/by_user", reduce=False, include_docs=True).all() self.assertTrue(isinstance(newcase.adate, dict)) self.assertEqual(date(2012,02,01), newcase.adate["#text"]) self.assertEqual("i am an attribute", newcase.adate["@someattr"]) self.assertTrue(isinstance(newcase.dateattr, dict)) self.assertEqual("this shouldn't break", newcase.dateattr["#text"]) self.assertEqual(date(2012,01,01), newcase.dateattr["@somedate"]) self.assertTrue(isinstance(newcase.stringattr, dict)) self.assertEqual("neither should this", newcase.stringattr["#text"]) self.assertEqual("i am a string", newcase.stringattr["@somestring"]) restore_payload = generate_restore_payload(dummy_user()) # ghetto self.assertTrue('<dateattr somedate="2012-01-01">' in restore_payload) self.assertTrue('<stringattr somestring="i am a string">' in restore_payload)
def testUserRestoreWithCase(self): file_path = os.path.join(os.path.dirname(__file__), "data", "create_short.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data, domain=self.domain) process_cases(form) expected_case_block = """ <case case_id="asdf" date_modified="2010-06-29T13:42:50.000000Z" user_id="foo" xmlns="http://commcarehq.org/case/transaction/v2"> <create> <case_type>test_case_type</case_type> <case_name>test case name</case_name> <owner_id>foo</owner_id> </create> <update> <external_id>someexternal</external_id> </update> </case>""" restore_payload = generate_restore_payload( project=Domain(name=self.domain), user=dummy_user(), items=True, version=V3 ) sync_log_id = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).one().get_id check_xml_line_by_line( self, dummy_restore_xml(sync_log_id, expected_case_block, items=4), restore_payload )
def testOtherUserCloses(self): # create a case from one user case_id = "other_user_closes" self._createCaseStubs([case_id], owner_id=SHARED_ID) # sync then close case from another user self.other_sync_log = synclog_from_restore_payload( generate_restore_payload(self.other_user) ) close_block = CaseBlock( create=False, case_id=case_id, user_id=USER_ID, version=V2, close=True ).as_xml() self._postFakeWithSyncToken( close_block, self.other_sync_log.get_id ) # original user syncs again # make sure close block appears assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id)
def testUserLoggedIntoMultipleDevices(self): # test that a child case created by the same user from a different device # gets included in the sync parent_id = "parent" child_id = "child" self._createCaseStubs([parent_id]) # create child case using a different sync log ID other_sync_log = synclog_from_restore_payload( generate_restore_payload(self.user, version="2.0") ) child = CaseBlock( create=True, case_id=child_id, user_id=USER_ID, owner_id=USER_ID, version=V2, index={'mother': ('mother', parent_id)} ).as_xml() self._postFakeWithSyncToken(child, other_sync_log.get_id) # ensure child case is included in sync using original sync log ID assert_user_has_case(self, self.user, child_id, restore_id=self.sync_log.get_id)
def test_basic_properties(self): # kick off a restore to generate the sync log generate_restore_payload(self.project, self.restore_user, items=True) sync_log = SyncLog.last_for_user(self.restore_user.user_id) self.assertEqual(self.restore_user.user_id, sync_log.user_id) self.assertEqual(self.restore_user.domain, sync_log.domain)
def test_selective_program_sync(self): user = self.user Program( domain=user.domain, name="test1", code="t1" ).save() program_list = Program.by_domain(user.domain) program_xml = self.generate_program_xml(program_list, user) fixture_original = program_fixture_generator(user, V1) generate_restore_payload(self.domain_obj, user) self.assertXmlEqual( program_xml, ElementTree.tostring(fixture_original[0]) ) first_sync = sorted(SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False ).all(), key=lambda x: x.date)[-1] # make sure the time stamp on this first sync is # not on the same second that the programs were created first_sync.date += datetime.timedelta(seconds=1) # second sync is before any changes are made, so there should # be no programs synced fixture_pre_change = program_fixture_generator(user, V1, last_sync=first_sync) generate_restore_payload(self.domain_obj, user) self.assertEqual( [], fixture_pre_change, "Fixture was not empty on second sync" ) second_sync = sorted(SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False ).all(), key=lambda x: x.date)[-1] self.assertTrue(first_sync._id != second_sync._id) # save should make the program more recently updated than the # last sync for program in program_list: program.save() # now that we've updated a program, we should get # program data in sync again fixture_post_change = program_fixture_generator(user, V1, last_sync=second_sync) # regenerate the fixture xml to make sure it is still legit self.assertXmlEqual( program_xml, ElementTree.tostring(fixture_post_change[0]) )
def testMultiUserEdits(self): time = datetime.utcnow() # create a case from one user case_id = "multi_user_edits" self._createCaseStubs([case_id], owner_id=SHARED_ID) # both users syncs self.sync_log = synclog_from_restore_payload( generate_restore_payload(self.user) ) self.other_sync_log = synclog_from_restore_payload( generate_restore_payload(self.other_user) ) # update case from same user my_change = CaseBlock( create=False, date_modified=time, case_id=case_id, user_id=USER_ID, version=V2, update={'greeting': 'hello'} ).as_xml(format_datetime=json_format_datetime) self._postFakeWithSyncToken( my_change, self.sync_log.get_id ) # update from another user their_change = CaseBlock( create=False, date_modified=time, case_id=case_id, user_id=USER_ID, version=V2, update={'greeting_2': 'hello'} ).as_xml(format_datetime=json_format_datetime) self._postFakeWithSyncToken( their_change, self.other_sync_log.get_id ) # original user syncs again # make sure updates both appear (and merge?) joint_change = CaseBlock( create=False, date_modified=time, case_id=case_id, user_id=USER_ID, version=V2, update={ 'greeting': 'hello', 'greeting_2': 'hello' }, owner_id=SHARED_ID, case_name='', case_type='mother', ).as_xml(format_datetime=json_format_datetime) check_user_has_case(self, self.user, joint_change, restore_id=self.sync_log.get_id, version=V2) check_user_has_case(self, self.other_user, joint_change, restore_id=self.other_sync_log.get_id, version=V2)
<date_opened>2010-06-29</date_opened> </update> </case>""".format(user_id=self.restore_user.user_id) check_xml_line_by_line( self, expected_v2_case_block, xml.get_case_xml( result.case, [case_const.CASE_ACTION_CREATE, case_const.CASE_ACTION_UPDATE], version="2.0", ), ) restore_payload = generate_restore_payload( project=self.project, user=self.restore_user, items=True, ) sync_log_id = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).one().get_id check_xml_line_by_line( self, dummy_restore_xml(sync_log_id, expected_case_block, items=4, user=self.restore_user), restore_payload) def testSyncTokenWithItems(self):
def testOtherUserReassignsIndexed(self): # create a parent and child case (with index) from one user parent_id = "other_reassigns_index_parent" case_id = "other_reassigns_index_child" self._createCaseStubs([parent_id]) child = CaseBlock( create=True, case_id=case_id, user_id=USER_ID, owner_id=SHARED_ID, version=V2, index={'mother': ('mother', parent_id)} ).as_xml() self._postFakeWithSyncToken(child, self.sync_log.get_id) # assign the parent case away from the same user parent_update = CaseBlock( create=False, case_id=parent_id, user_id=USER_ID, owner_id=OTHER_USER_ID, update={"greeting": "hello"}, version=V2).as_xml() self._postFakeWithSyncToken(parent_update, self.sync_log.get_id) # sync cases to second user self.other_sync_log = synclog_from_restore_payload( generate_restore_payload(self.other_user) ) # change the child's owner from another user child_reassignment = CaseBlock( create=False, case_id=case_id, user_id=OTHER_USER_ID, owner_id=OTHER_USER_ID, version=V2, update={"childgreeting": "hi!"}, ).as_xml() self._postFakeWithSyncToken(child_reassignment, self.other_sync_log.get_id) # also change the parent from the second user other_parent_update = CaseBlock( create=False, case_id=parent_id, user_id=OTHER_USER_ID, owner_id=OTHER_USER_ID, update={"other_greeting": "something new"}, version=V2).as_xml() self._postFakeWithSyncToken(other_parent_update, self.other_sync_log.get_id) # original user syncs again self.sync_log = SyncLog.last_for_user(self.user.user_id) # both cases should sync to original user with updated ownership / edits assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id) assert_user_has_case(self, self.user, parent_id, restore_id=self.sync_log.get_id) # Ghetto payload = generate_restore_payload(self.user, self.sync_log.get_id, version=V2) self.assertTrue("something new" in payload) self.assertTrue("hi!" in payload) # change the parent again from the second user other_parent_update = CaseBlock( create=False, case_id=parent_id, user_id=OTHER_USER_ID, owner_id=OTHER_USER_ID, update={"other_greeting": "something different"}, version=V2).as_xml() self._postFakeWithSyncToken(other_parent_update, self.other_sync_log.get_id) # original user syncs again self.sync_log = SyncLog.last_for_user(self.user.user_id) # should be no changes assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id) assert_user_doesnt_have_case(self, self.user, parent_id, restore_id=self.sync_log.get_id) # change the child again from the second user other_child_update = CaseBlock( create=False, case_id=case_id, user_id=OTHER_USER_ID, owner_id=OTHER_USER_ID, version=V2, update={"childgreeting": "hi changed!"}, ).as_xml() self._postFakeWithSyncToken(other_child_update, self.other_sync_log.get_id) # original user syncs again self.sync_log = SyncLog.last_for_user(self.user.user_id) # should be no changes assert_user_doesnt_have_case(self, self.user, case_id, restore_id=self.sync_log.get_id) assert_user_doesnt_have_case(self, self.user, parent_id, restore_id=self.sync_log.get_id) # change owner of child back to orginal user from second user child_reassignment = CaseBlock( create=False, case_id=case_id, user_id=OTHER_USER_ID, owner_id=USER_ID, version=V2 ).as_xml() self._postFakeWithSyncToken(child_reassignment, self.other_sync_log.get_id) # original user syncs again self.sync_log = SyncLog.last_for_user(self.user.user_id) # both cases should now sync assert_user_has_case(self, self.user, case_id, restore_id=self.sync_log.get_id) assert_user_has_case(self, self.user, parent_id, restore_id=self.sync_log.get_id) # ghetto payload = generate_restore_payload(self.user, self.sync_log.get_id, version=V2) self.assertTrue("something different" in payload) self.assertTrue("hi changed!" in payload)
def _test_sync_token(self, items): """ Tests sync token / sync mode support """ file_path = os.path.join(os.path.dirname(__file__), "data", "create_short.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data, domain=self.project.name) process_cases(form) time.sleep(1) restore_payload = generate_restore_payload(self.project, dummy_user(), items=items) sync_log_id = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False ).one().get_id expected_restore_payload = dummy_restore_xml( sync_log_id, const.CREATE_SHORT, items=4 if items else None, ) check_xml_line_by_line(self, expected_restore_payload, restore_payload) time.sleep(1) sync_restore_payload = generate_restore_payload( project=self.project, user=dummy_user(), restore_id=sync_log_id, items=items, ) all_sync_logs = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).all() [latest_log] = [log for log in all_sync_logs if log.get_id != sync_log_id] # should no longer have a case block in the restore XML check_xml_line_by_line( self, dummy_restore_xml(latest_log.get_id, items=3 if items else None), sync_restore_payload, ) # apply an update time.sleep(1) file_path = os.path.join(os.path.dirname(__file__), "data", "update_short.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data, domain=self.project.name) process_cases(form) time.sleep(1) sync_restore_payload = generate_restore_payload( self.project, user=dummy_user(), restore_id=latest_log.get_id, items=items, ) all_sync_logs = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).all() [even_latest_log] = [log for log in all_sync_logs if log.get_id != sync_log_id and log.get_id != latest_log.get_id] # case block should come back expected_sync_restore_payload = dummy_restore_xml( even_latest_log.get_id, const.UPDATE_SHORT, items=4 if items else None, ) check_xml_line_by_line(self, expected_sync_restore_payload, sync_restore_payload)
def testUserRestoreWithCase(self): file_path = os.path.join(os.path.dirname(__file__), "data", "create_short.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data, domain=self.project.name) # implicit length assertion [newcase] = process_cases(form) user = dummy_user() self.assertEqual(1, len(list( BatchedCaseSyncOperation(RestoreState(self.project, user, RestoreParams())).get_all_case_updates() ))) expected_case_block = """ <case> <case_id>asdf</case_id> <date_modified>2010-06-29T13:42:50.000000Z</date_modified> <create> <case_type_id>test_case_type</case_type_id> <user_id>foo</user_id> <case_name>test case name</case_name> <external_id>someexternal</external_id> </create> </case>""" check_xml_line_by_line(self, expected_case_block, xml.get_case_xml(newcase, [case_const.CASE_ACTION_CREATE, case_const.CASE_ACTION_UPDATE])) # check v2 expected_v2_case_block = """ <case case_id="asdf" date_modified="2010-06-29T13:42:50.000000Z" user_id="foo" xmlns="http://commcarehq.org/case/transaction/v2" > <create> <case_type>test_case_type</case_type> <case_name>test case name</case_name> <owner_id>foo</owner_id> </create> <update> <external_id>someexternal</external_id> </update> </case>""" check_xml_line_by_line( self, expected_v2_case_block, xml.get_case_xml( newcase, [case_const.CASE_ACTION_CREATE, case_const.CASE_ACTION_UPDATE], version="2.0", ), ) restore_payload = generate_restore_payload( project=self.project, user=dummy_user(), items=True, ) sync_log_id = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).one().get_id check_xml_line_by_line( self, dummy_restore_xml(sync_log_id, expected_case_block, items=4), restore_payload )
def _test_sync_token(self, items): """ Tests sync token / sync mode support """ xml_data = self.get_xml('create_short') xml_data = xml_data.format(user_id=self.restore_user.user_id) submit_form_locally(xml_data, domain=self.project.name) restore_payload = generate_restore_payload(self.project, self.restore_user, items=items) sync_log_id = SyncLog.view("phone/sync_logs_by_user", include_docs=True, reduce=False).one().get_id expected_restore_payload = dummy_restore_xml( sync_log_id, const.CREATE_SHORT.format(user_id=self.restore_user.user_id), items=4 if items else None, user=self.restore_user, ) check_xml_line_by_line(self, expected_restore_payload, restore_payload) sync_restore_payload = generate_restore_payload( project=self.project, user=self.restore_user, restore_id=sync_log_id, items=items, ) all_sync_logs = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).all() [latest_log ] = [log for log in all_sync_logs if log.get_id != sync_log_id] # should no longer have a case block in the restore XML check_xml_line_by_line( self, dummy_restore_xml( latest_log.get_id, items=3 if items else None, user=self.restore_user, ), sync_restore_payload, ) # apply an update xml_data = self.get_xml('update_short') xml_data = xml_data.format(user_id=self.restore_user.user_id) submit_form_locally(xml_data, domain=self.project.name) sync_restore_payload = generate_restore_payload( self.project, user=self.restore_user, restore_id=latest_log.get_id, items=items, ) all_sync_logs = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).all() [even_latest_log] = [ log for log in all_sync_logs if log.get_id != sync_log_id and log.get_id != latest_log.get_id ] # case block should come back expected_sync_restore_payload = dummy_restore_xml( even_latest_log.get_id, const.UPDATE_SHORT.format(user_id=self.restore_user.user_id), items=4 if items else None, user=self.restore_user) check_xml_line_by_line(self, expected_sync_restore_payload, sync_restore_payload)
def testUserRestoreWithCase(self): xml_data = self.get_xml('create_short') xml_data = xml_data.format(user_id=self.restore_user.user_id) # implicit length assertion _, _, [newcase] = submit_form_locally(xml_data, domain=self.project.name) expected_case_block = """ <case> <case_id>asdf</case_id> <date_modified>2010-06-29T13:42:50.000000Z</date_modified> <create> <case_type_id>test_case_type</case_type_id> <user_id>{user_id}</user_id> <case_name>test case name</case_name> <external_id>someexternal</external_id> </create> <update> <date_opened>2010-06-29</date_opened> </update> </case>""".format(user_id=self.restore_user.user_id) check_xml_line_by_line( self, expected_case_block, xml.get_case_xml( newcase, [case_const.CASE_ACTION_CREATE, case_const.CASE_ACTION_UPDATE ])) # check v2 expected_v2_case_block = """ <case case_id="asdf" date_modified="2010-06-29T13:42:50.000000Z" user_id="{user_id}" xmlns="http://commcarehq.org/case/transaction/v2" > <create> <case_type>test_case_type</case_type> <case_name>test case name</case_name> <owner_id>{user_id}</owner_id> </create> <update> <external_id>someexternal</external_id> <date_opened>2010-06-29</date_opened> </update> </case>""".format(user_id=self.restore_user.user_id) check_xml_line_by_line( self, expected_v2_case_block, xml.get_case_xml( newcase, [case_const.CASE_ACTION_CREATE, case_const.CASE_ACTION_UPDATE], version="2.0", ), ) restore_payload = generate_restore_payload( project=self.project, user=self.restore_user, items=True, ) sync_log_id = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).one().get_id check_xml_line_by_line( self, dummy_restore_xml(sync_log_id, expected_case_block, items=4, user=self.restore_user), restore_payload)
def testUserRestoreWithCase(self): file_path = os.path.join(os.path.dirname(__file__), "data", "create_short.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) user = dummy_user() # implicit length assertion [newcase] = CommCareCase.view("case/by_user", reduce=False, include_docs=True).all() self.assertEqual(1, len(list(BatchedCaseSyncOperation(user, None).get_all_case_updates()))) expected_case_block = """ <case> <case_id>asdf</case_id> <date_modified>2010-06-29T13:42:50Z</date_modified> <create> <case_type_id>test_case_type</case_type_id> <user_id>foo</user_id> <case_name>test case name</case_name> <external_id>someexternal</external_id> </create> </case>""" check_xml_line_by_line(self, expected_case_block, xml.get_case_xml(newcase, [case_const.CASE_ACTION_CREATE, case_const.CASE_ACTION_UPDATE])) # check v2 expected_v2_case_block = """ <case case_id="asdf" date_modified="2010-06-29T13:42:50Z" user_id="foo" xmlns="http://commcarehq.org/case/transaction/v2" > <create> <case_type>test_case_type</case_type> <case_name>test case name</case_name> <owner_id>foo</owner_id> </create> <update> <external_id>someexternal</external_id> </update> </case>""" check_xml_line_by_line( self, expected_v2_case_block, xml.get_case_xml( newcase, [case_const.CASE_ACTION_CREATE, case_const.CASE_ACTION_UPDATE], version="2.0", ), ) restore_payload = generate_restore_payload( user=dummy_user(), items=True, ) sync_log_id = SyncLog.view( "phone/sync_logs_by_user", include_docs=True, reduce=False, ).one().get_id check_xml_line_by_line( self, dummy_restore_xml(sync_log_id, expected_case_block, items=4), restore_payload )
def get_ota_balance_xml(project, user): xml = generate_restore_payload(project, user.to_ota_restore_user(), version=V2) return extract_balance_xml(xml)
def get_ota_balance_xml(project, user): xml = generate_restore_payload(project, user.to_casexml_user(), version=V2) return extract_balance_xml(xml)