示例#1
0
    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)
示例#2
0
 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)
示例#3
0
    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])
        )
示例#4
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()
示例#5
0
    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
示例#6
0
    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()
示例#7
0
 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)
示例#8
0
    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)
示例#9
0
 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))
示例#10
0
    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
        )
示例#11
0
    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
        )
示例#12
0
    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]))
示例#13
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)
示例#14
0
 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")
         )
示例#15
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,
     )
示例#16
0
    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)
示例#17
0
    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)
示例#18
0
    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)
示例#19
0
 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)
示例#20
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,
                                                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,
     )
示例#21
0
 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)
示例#22
0
    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
        )
示例#23
0
    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)
示例#24
0
    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)
示例#25
0
 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)
示例#26
0
    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])
        )
示例#27
0
 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)
示例#28
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)
示例#29
0
                <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):
示例#30
0
    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)
示例#31
0
    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)
示例#32
0
    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
        )
示例#33
0
    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)
示例#34
0
    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)
示例#35
0
    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
        )
示例#36
0
def get_ota_balance_xml(project, user):
    xml = generate_restore_payload(project,
                                   user.to_ota_restore_user(),
                                   version=V2)
    return extract_balance_xml(xml)
示例#37
0
def get_ota_balance_xml(project, user):
    xml = generate_restore_payload(project, user.to_casexml_user(), version=V2)
    return extract_balance_xml(xml)