def testDuplicateCasePropertiesBug(self): """ How do we do when submitting multiple values for the same property in an update block """ self.assertEqual( 0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "duplicate_case_properties.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) # before the bug was fixed this call failed process_cases(form) case = CommCareCase.get(form.xpath("form/case/@case_id")) # make sure the property is there, but empty self.assertEqual("", case.foo) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "duplicate_case_properties_2.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) case = CommCareCase.get(form.xpath("form/case/@case_id")) # make sure the property takes the last defined value self.assertEqual("2", case.bar)
def testBasicEdit(self): first_file = os.path.join(os.path.dirname(__file__), "data", "duplicate.xml") edit_file = os.path.join(os.path.dirname(__file__), "data", "edit.xml") with open(first_file, "rb") as f: xml_data1 = f.read() with open(edit_file, "rb") as f: xml_data2 = f.read() doc = post_xform_to_couch(xml_data1) self.assertEqual("7H46J37FGH3", doc.get_id) self.assertEqual("XFormInstance", doc.doc_type) self.assertEqual("", doc.form['vitals']['height']) self.assertEqual("other", doc.form['assessment']['categories']) doc = post_xform_to_couch(xml_data2) self.assertEqual("7H46J37FGH3", doc.get_id) self.assertEqual("XFormInstance", doc.doc_type) self.assertEqual("100", doc.form['vitals']['height']) self.assertEqual("Edited Baby!", doc.form['assessment']['categories']) doc = XFormDeprecated.view('couchforms/edits', include_docs=True).first() self.assertEqual("7H46J37FGH3", doc.orig_id) self.assertNotEqual("7H46J37FGH3", doc.get_id) self.assertEqual(XFormDeprecated.__name__, doc.doc_type) self.assertEqual("", doc.form['vitals']['height']) self.assertEqual("other", doc.form['assessment']['categories'])
def testDuplicateCasePropertiesBug(self): """ How do we do when submitting multiple values for the same property in an update block """ self.assertEqual(0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "duplicate_case_properties.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) # before the bug was fixed this call failed process_cases(form) case = CommCareCase.get(form.xpath("form/case/@case_id")) # make sure the property is there, but empty self.assertEqual("", case.foo) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "duplicate_case_properties_2.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) case = CommCareCase.get(form.xpath("form/case/@case_id")) # make sure the property takes the last defined value self.assertEqual("2", case.bar)
def testCantPwnCase(self): form = post_xform_to_couch(ALICE_XML) form.domain = ALICE_DOMAIN (case,) = process_cases(form) case_id = case.case_id form = post_xform_to_couch(EVE_XML) form.domain = EVE_DOMAIN with self.assertRaises(IllegalCaseId): process_cases(form) self.assertFalse(hasattr(CommCareCase.get(case_id), 'plan_to_buy_gun')) form = post_xform_to_couch(ALICE_UPDATE_XML) form.domain = ALICE_DOMAIN process_cases(form) self.assertEqual(CommCareCase.get(case_id).plan_to_buy_gun, 'no')
def testAttachInUpdate(self): self.testAttachInCreate() file_path = os.path.join(os.path.dirname(__file__), "data", "attachments", "update_with_attach.xml") with open(file_path, "rb") as f: xml_data = f.read() attach_name = "house.jpg" attachment_path = os.path.join(os.path.dirname(__file__), "data", "attachments", attach_name) with open(attachment_path, "rb") as attachment: uf = UploadedFile(attachment, attach_name) form = post_xform_to_couch(xml_data, {attach_name: uf}) self.assertEqual(1, len(form.attachments)) fileback = form.fetch_attachment(attach_name) # rewind the pointer before comparing attachment.seek(0) self.assertEqual(hashlib.md5(fileback).hexdigest(), hashlib.md5(attachment.read()).hexdigest()) process_cases(sender="testharness", xform=form) case = CommCareCase.get(form.xpath("form/case/case_id")) self.assertEqual(2, len(case.attachments)) self.assertEqual(form.get_id, case.attachments[1][0]) self.assertEqual(attach_name, case.attachments[1][1])
def _test(custom_format_args): case_id = uuid.uuid4().hex format_args = { 'case_id': case_id, 'form_id': uuid.uuid4().hex, 'user_id': uuid.uuid4().hex, 'case_name': 'data corner cases', 'case_type': 'datatype-check', } format_args.update(custom_format_args) for filename in [ 'bugs_in_case_create_datatypes.xml', 'bugs_in_case_update_datatypes.xml' ]: file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", filename) with open(file_path, "rb") as f: xml_data = f.read() xml_data = xml_data.format(**format_args) form = post_xform_to_couch(xml_data) # before the bug was fixed this call failed process_cases(form) case = CommCareCase.get(case_id) self.assertEqual(format_args['user_id'], case.user_id) self.assertEqual(format_args['case_name'], case.name) self.assertEqual(format_args['case_type'], case.type)
def post(request, callback=None): """ XForms can get posted here. They will be forwarded to couch. Just like play, if you specify a callback you get called, otherwise you get a generic response. Callbacks follow a different signature as play, only passing in the document (since we don't know what xform was being posted to) """ # odk/javarosa preprocessing. These come in in different ways. attachments = {} if request.META['CONTENT_TYPE'].startswith('multipart/form-data'): #it's an standard form submission (eg ODK) #this does an assumption that ODK submissions submit using the form parameter xml_submission_file #todo: this should be made more flexibly to handle differeing params for xform submission instance = request.FILES['xml_submission_file'].read() for key, item in request.FILES.items(): if key != "xml_submission_file": attachments[key] = item else: #else, this is a raw post via a j2me client of xml (or touchforms) #todo, multipart raw submissions need further parsing capacity. instance = request.raw_post_data try: doc = post_xform_to_couch(instance, attachments=attachments) if callback: return callback(doc) return HttpResponse("Thanks! Your new xform id is: %s" % doc["_id"], status=201) except Exception, e: logging.exception(e) return HttpResponseServerError("FAIL")
def _do_submit(self, xml_data, dict_attachments): """ RequestFactory submitter - simulates direct submission to server directly (no need to call process case after fact) """ form = post_xform_to_couch(xml_data, dict_attachments) form.domain = TEST_DOMAIN self.assertEqual(len(dict_attachments.keys()), len(form.attachments)) process_cases(form)
def test_basic_duplicate(self): xml_data = self._get_file() doc = post_xform_to_couch(xml_data) self.assertEqual(self.ID, doc.get_id) self.assertEqual("XFormInstance", doc.doc_type) doc.domain = 'test-domain' doc.save() doc = post_xform_to_couch(xml_data, domain='test-domain') self.assertNotEqual(self.ID, doc.get_id) self.assertEqual("XFormDuplicate", doc.doc_type) self.assertTrue(self.ID in doc.problem) dupe_id = doc.get_id XFormInstance.get_db().delete_doc(self.ID) XFormInstance.get_db().delete_doc(dupe_id)
def test_basic_duplicate(self): xml_data = self._get_file() doc = post_xform_to_couch(xml_data) self.assertEqual("7H46J37FGH3", doc.get_id) self.assertEqual("XFormInstance", doc.doc_type) doc.domain = 'test-domain' doc.save() doc = post_xform_to_couch(xml_data, domain='test-domain') self.assertNotEqual("7H46J37FGH3", doc.get_id) self.assertEqual("XFormDuplicate", doc.doc_type) self.assertTrue("7H46J37FGH3" in doc.problem) dupe_id = doc.get_id XFormInstance.get_db().delete_doc("7H46J37FGH3") XFormInstance.get_db().delete_doc(dupe_id)
def testOTARestore(self): self.assertEqual(0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "multicase", "parallel_cases.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(sender="testharness", xform=form) self.assertEqual(4, len(CommCareCase.view("case/by_user", reduce=False).all()))
def testSyncToken(self): """ 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) process_cases(sender="testharness", xform=form) time.sleep(1) restore_payload = generate_restore_payload(dummy_user()) # implicit length assertion [sync_log] = SyncLog.view("phone/sync_logs_by_user", include_docs=True, reduce=False).all() check_xml_line_by_line(self, dummy_restore_xml(sync_log.get_id, const.CREATE_SHORT), restore_payload) time.sleep(1) sync_restore_payload = generate_restore_payload(dummy_user(), sync_log.get_id) [latest_log] = [log for log in \ SyncLog.view("phone/sync_logs_by_user", include_docs=True, reduce=False).all() \ if log.get_id != sync_log.get_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), 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) process_cases(sender="testharness", xform=form) time.sleep(1) sync_restore_payload = generate_restore_payload(dummy_user(), latest_log.get_id) [even_latest_log] = [log for log in \ SyncLog.view("phone/sync_logs_by_user", include_docs=True, reduce=False).all() \ if log.get_id != sync_log.get_id and log.get_id != latest_log.get_id] # case block should come back check_xml_line_by_line(self, dummy_restore_xml(even_latest_log.get_id, const.UPDATE_SHORT), sync_restore_payload)
def test_auth_context(self): file_path = os.path.join(os.path.dirname(__file__), "data", "meta.xml") xml_data = open(file_path, "rb").read() def process(xform): xform['auth_context'] = DefaultAuthContext().to_json() xform = post_xform_to_couch(xml_data, process=process) self.assertEqual(xform.auth_context, {'doc_type': 'DefaultAuthContext'})
def setUp(self): for item in XFormInstance.view("couchforms/by_xmlns", include_docs=True, reduce=False).all(): item.delete() file_path = os.path.join(os.path.dirname(__file__), "data", "meta.xml") with open(file_path, "rb") as f: xml_data = f.read() self.instance = post_xform_to_couch(xml_data)
def _postWithSyncToken(self, filename, token_id): file_path = os.path.join(os.path.dirname(__file__), "data", filename) with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) # set last sync token on the form before saving form.last_sync_token = token_id process_cases(form) return form
def test_wrong_domain(self): domain = 'test-domain' XFormInstance.get_db().save_doc({ '_id': self.ID, 'doc_type': 'XFormInstance', 'domain': 'wrong-domain', }) doc = post_xform_to_couch(instance=self._get_file(), domain=domain) self.assertNotEqual(doc.get_id, self.ID)
def testCasesInRepeats(self): self.assertEqual(0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "multicase", "case_in_repeats.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) cases = self._get_cases() self.assertEqual(3, len(cases)) self._check_ids(form, cases)
def testTopLevelExclusion(self): """ Entire forms tagged as device logs should be excluded """ self.assertEqual(0, len(CommCareCase.view("case/by_user", include_docs=True, reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "exclusion", "device_report.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) self.assertEqual(0, len(CommCareCase.view("case/by_user", include_docs=True, reduce=False).all()))
def testMixed(self): self.assertEqual( 0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "multicase", "mixed_cases.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) self.assertEqual( 4, len(CommCareCase.view("case/by_user", reduce=False).all()))
def test_wrong_doc_type(self): domain = 'test-domain' id = '7H46J37FGH3' XFormInstance.get_db().save_doc({ '_id': id, 'doc_type': 'Foo', 'domain': domain, }) doc = post_xform_to_couch(instance=self._get_file(), domain=domain) self.assertNotEqual(doc.get_id, id)
def testStringFormatProblems(self): """ If two forms share an ID it's a conflict """ self.assertEqual(0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "string_formatting.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) # before the bug was fixed this call failed process_cases(form)
def testParseClose(self): self.testParseCreate() file_path = os.path.join(os.path.dirname(__file__), "data", "v2", "basic_close.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(sender="testharness", xform=form) case = CommCareCase.get("foo-case-id") self.assertTrue(case.closed)
def testLotsOfSubcases(self): """ How do we do when submitting a form with multiple blocks for the same case? """ self.assertEqual(0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "lots_of_subcases.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) # before the bug was fixed this call failed process_cases(form) self.assertEqual(11, len(CommCareCase.view("case/by_user", reduce=False).all()))
def testCasesInRepeats(self): self.assertEqual( 0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "multicase", "case_in_repeats.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) cases = self._get_cases() self.assertEqual(3, len(cases)) self._check_ids(form, cases)
def testBasicDuplicate(self): file_path = os.path.join(os.path.dirname(__file__), "data", "duplicate.xml") with open(file_path, "rb") as f: xml_data = f.read() doc = post_xform_to_couch(xml_data) self.assertEqual("7H46J37FGH3", doc.get_id) self.assertEqual("XFormInstance", doc.doc_type) doc = post_xform_to_couch(xml_data) self.assertNotEqual("7H46J37FGH3", doc.get_id) self.assertEqual("XFormDuplicate", doc.doc_type) self.assertTrue("7H46J37FGH3" in doc.problem) dupe_id = doc.get_id XFormInstance.get_db().delete_doc("7H46J37FGH3") XFormInstance.get_db().delete_doc(dupe_id)
def replace_ids_and_post(xml_data, case_id_override=None, referral_id_override=None): # from our test forms, replace the UIDs so we don't get id conflicts uid, case_id, ref_id = (uuid.uuid4().hex for i in range(3)) if case_id_override: case_id = case_id_override if referral_id_override: ref_id = referral_id_override xml_data = xml_data.replace("REPLACE_UID", uid) xml_data = xml_data.replace("REPLACE_CASEID", case_id) xml_data = xml_data.replace("REPLACE_REFID", ref_id) doc = post_xform_to_couch(xml_data) return (doc.get_id, uid, case_id, ref_id)
def testParseWithIndices(self): self.testParseCreate() user_id = "bar-user-id" for prereq in ["some_referenced_id", "some_other_referenced_id"]: post_case_blocks([ CaseBlock( create=True, case_id=prereq, user_id=user_id, version=V2).as_xml(format_datetime=json_format_datetime) ]) file_path = os.path.join(os.path.dirname(__file__), "data", "v2", "index_update.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) case = CommCareCase.get("foo-case-id") self.assertEqual(2, len(case.indices)) self.assertTrue(case.has_index("foo_ref")) self.assertTrue(case.has_index("baz_ref")) self.assertEqual("bar", case.get_index("foo_ref").referenced_type) self.assertEqual("some_referenced_id", case.get_index("foo_ref").referenced_id) self.assertEqual("bop", case.get_index("baz_ref").referenced_type) self.assertEqual("some_other_referenced_id", case.get_index("baz_ref").referenced_id) # check the action self.assertEqual(2, len(case.actions)) [_, index_action] = case.actions self.assertEqual(const.CASE_ACTION_INDEX, index_action.action_type) self.assertEqual(2, len(index_action.indices)) # quick test for ota restore v2response = phone_views.xml_for_case(HttpRequest(), case.get_id, version="2.0") expected_v2_response = """ <case case_id="foo-case-id" date_modified="2011-12-07T13:42:50Z" user_id="bar-user-id" xmlns="http://commcarehq.org/case/transaction/v2"> <create> <case_type>v2_case_type</case_type> <case_name>test case name</case_name> <owner_id>bar-user-id</owner_id> </create> <index> <baz_ref case_type="bop">some_other_referenced_id</baz_ref> <foo_ref case_type="bar">some_referenced_id</foo_ref> </index> </case>""" check_xml_line_by_line(self, expected_v2_response, v2response.content)
def testNestedExclusion(self): """ Blocks inside forms tagged as device logs should be excluded """ self.assertEqual(0, len(CommCareCase.view("case/by_user", include_docs=True, reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "exclusion", "nested_device_report.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) self.assertEqual(1, len(CommCareCase.view("case/by_user", include_docs=True, reduce=False).all())) case = CommCareCase.get("case_in_form") self.assertEqual("form case", case.name)
def testCloudantRaceCondition(self): file_path = os.path.join(os.path.dirname(__file__), "data", "cloudant-template.xml") with open(file_path) as f: xml_data = f.read() count = 1000 for i in range(count): instance_id = uuid.uuid4().hex case_id = uuid.uuid4().hex xform = post_xform_to_couch(xml_data.format(instance_id=instance_id, case_id=case_id)) xform.foo = "bar" xform.save() print "%s/%s ok" % (i, count)
def testParseClose(self): self.testParseCreate() file_path = os.path.join(os.path.dirname(__file__), "data", "v2", "basic_close.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) case = CommCareCase.get("foo-case-id") self.assertTrue(case.closed) self.assertEqual("bar-user-id", case.closed_by)
def testDateInCaseNameBug(self): """ How do we do when submitting a case name that looks like a date? """ self.assertEqual(0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "date_in_case_name.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) # before the bug was fixed this call failed process_cases(sender="testharness", xform=form) case = CommCareCase.get(form.xpath("form/case/case_id")) self.assertEqual("2011-11-16", case.name)
def testStringFormatProblems(self): """ If two forms share an ID it's a conflict """ self.assertEqual( 0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "string_formatting.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) # before the bug was fixed this call failed process_cases(form)
def test_basic_edit(self): first_file = os.path.join(os.path.dirname(__file__), "data", "duplicate.xml") edit_file = os.path.join(os.path.dirname(__file__), "data", "edit.xml") with open(first_file, "rb") as f: xml_data1 = f.read() with open(edit_file, "rb") as f: xml_data2 = f.read() docs = [] doc = post_xform_to_couch(xml_data1) self.assertEqual(self.ID, doc.get_id) self.assertEqual("XFormInstance", doc.doc_type) self.assertEqual("", doc.form['vitals']['height']) self.assertEqual("other", doc.form['assessment']['categories']) doc.domain = 'test-domain' doc.save() doc = post_xform_to_couch(xml_data2, domain='test-domain') self.assertEqual(self.ID, doc.get_id) self.assertEqual("XFormInstance", doc.doc_type) self.assertEqual("100", doc.form['vitals']['height']) self.assertEqual("Edited Baby!", doc.form['assessment']['categories']) docs.append(doc) doc = XFormDeprecated.view('couchforms/edits', include_docs=True).first() self.assertEqual(self.ID, doc.orig_id) self.assertNotEqual(self.ID, doc.get_id) self.assertEqual(XFormDeprecated.__name__, doc.doc_type) self.assertEqual("", doc.form['vitals']['height']) self.assertEqual("other", doc.form['assessment']['categories']) for doc in docs: doc.delete()
def testParseCreate(self): file_path = os.path.join(os.path.dirname(__file__), "data", "v2", "basic_create.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(sender="testharness", xform=form) case = CommCareCase.get("foo-case-id") self.assertFalse(case.closed) self.assertEqual("bar-user-id", case.user_id) self.assertEqual(datetime(2011, 12, 6, 13, 42, 50), case.modified_on) self.assertEqual("v2_case_type", case.type) self.assertEqual("test case name", case.name) self.assertEqual(1, len(case.actions))
def testCRSReg(self): file_path = os.path.join(os.path.dirname(__file__), "data", "crs_reg.xml") with open(file_path, "rb") as f: xml_data = f.read() self.instance = post_xform_to_couch(xml_data) transform = DocumentTransform(self.instance._doc, get_db()) self.assertTrue("IDENTIFIER" in json.dumps(transform.doc)) self.assertTrue("IDENTIFIER" in transform.attachments["form.xml"]) deidentified = deidentify_form(transform) self.assertTrue("IDENTIFIER" not in json.dumps(deidentified.doc)) self.assertTrue("IDENTIFIER" not in deidentified.attachments["form.xml"])
def testEmptyCaseId(self): """ How do we do when submitting an empty case id? """ self.assertEqual(0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "empty_id.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) try: process_cases(form) self.fail("Empty Id should crash") except: pass
def testParseNamedNamespace(self): file_path = os.path.join(os.path.dirname(__file__), "data", "v2", "named_namespace.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(sender="testharness", xform=form) case = CommCareCase.get("14cc2770-2d1c-49c2-b252-22d6ecce385a") self.assertFalse(case.closed) self.assertEqual("d5ce3a980b5b69e793445ec0e3b2138e", case.user_id) self.assertEqual(datetime(2011, 12, 27), case.modified_on) self.assertEqual("cc_bihar_pregnancy", case.type) self.assertEqual("TEST", case.name) self.assertEqual(2, len(case.actions))
def testConflictingIds(self): """ If two forms share an ID it's a conflict """ self.assertEqual(0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "id_conflicts.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) try: process_cases(form) self.fail("Previous statement should have raised an exception") except Exception: pass
def testParseWithIndices(self): self.testParseCreate() user_id = "bar-user-id" for prereq in ["some_referenced_id", "some_other_referenced_id"]: post_case_blocks( [ CaseBlock(create=True, case_id=prereq, user_id=user_id, version=V2).as_xml( format_datetime=json_format_datetime ) ] ) file_path = os.path.join(os.path.dirname(__file__), "data", "v2", "index_update.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) case = CommCareCase.get("foo-case-id") self.assertEqual(2, len(case.indices)) self.assertTrue(case.has_index("foo_ref")) self.assertTrue(case.has_index("baz_ref")) self.assertEqual("bar", case.get_index("foo_ref").referenced_type) self.assertEqual("some_referenced_id", case.get_index("foo_ref").referenced_id) self.assertEqual("bop", case.get_index("baz_ref").referenced_type) self.assertEqual("some_other_referenced_id", case.get_index("baz_ref").referenced_id) # check the action self.assertEqual(2, len(case.actions)) [_, index_action] = case.actions self.assertEqual(const.CASE_ACTION_INDEX, index_action.action_type) self.assertEqual(2, len(index_action.indices)) # quick test for ota restore v2response = phone_views.xml_for_case(HttpRequest(), case.get_id, version="2.0") expected_v2_response = """ <case case_id="foo-case-id" date_modified="2011-12-07T13:42:50Z" user_id="bar-user-id" xmlns="http://commcarehq.org/case/transaction/v2"> <create> <case_type>v2_case_type</case_type> <case_name>test case name</case_name> <owner_id>bar-user-id</owner_id> </create> <index> <baz_ref case_type="bop">some_other_referenced_id</baz_ref> <foo_ref case_type="bar">some_referenced_id</foo_ref> </index> </case>""" check_xml_line_by_line(self, expected_v2_response, v2response.content)
def testLotsOfSubcases(self): """ How do we do when submitting a form with multiple blocks for the same case? """ self.assertEqual( 0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "lots_of_subcases.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) # before the bug was fixed this call failed process_cases(form) self.assertEqual( 11, len(CommCareCase.view("case/by_user", reduce=False).all()))
def testParseNamedNamespace(self): file_path = os.path.join(os.path.dirname(__file__), "data", "v2", "named_namespace.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) case = CommCareCase.get("14cc2770-2d1c-49c2-b252-22d6ecce385a") self.assertFalse(case.closed) self.assertEqual("d5ce3a980b5b69e793445ec0e3b2138e", case.user_id) self.assertEqual(datetime(2011, 12, 27), case.modified_on) self.assertEqual("cc_bihar_pregnancy", case.type) self.assertEqual("TEST", case.name) self.assertEqual(2, len(case.actions))
def testEmptyCaseId(self): """ How do we do when submitting an empty case id? """ self.assertEqual( 0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "empty_id.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) try: process_cases(form) self.fail("Empty Id should crash") except: pass
def testConflictingIds(self): """ If two forms share an ID it's a conflict """ self.assertEqual( 0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "id_conflicts.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) try: process_cases(form) self.fail("Previous statement should have raised an exception") except Exception: pass
def testOutOfOrderSubmissions(self): dir = os.path.join(os.path.dirname(__file__), "data", "ordering") forms = [] for fname in ('create_oo.xml', 'update_oo.xml'): with open(os.path.join(dir, fname), "rb") as f: xml_data = f.read() forms.append(post_xform_to_couch(xml_data)) [create, update] = forms # process out of order process_cases(update) process_cases(create) case = CommCareCase.get('30bc51f6-3247-4966-b4ae-994f572e85fe') self.assertEqual('from the update form', case.pupdate) self.assertEqual('from the create form', case.pcreate) self.assertEqual('overridden by the update form', case.pboth)
def testCloudantRaceCondition(self): file_path = os.path.join(os.path.dirname(__file__), "data", "cloudant-template.xml") with open(file_path) as f: xml_data = f.read() count = 1000 for i in range(count): instance_id = uuid.uuid4().hex case_id = uuid.uuid4().hex xform = post_xform_to_couch( xml_data.format( instance_id=instance_id, case_id=case_id, )) xform.foo = 'bar' xform.save() print '%s/%s ok' % (i, count)
def testParseUpdate(self): self.testParseCreate() file_path = os.path.join(os.path.dirname(__file__), "data", "v2", "basic_update.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) case = CommCareCase.get("foo-case-id") self.assertFalse(case.closed) self.assertEqual("bar-user-id", case.user_id) self.assertEqual(datetime(2011, 12, 7, 13, 42, 50), case.modified_on) self.assertEqual("updated_v2_case_type", case.type) self.assertEqual("updated case name", case.name) self.assertEqual("something dynamic", case.dynamic) self.assertEqual(2, len(case.actions)) self.assertEqual("bar-user-id", case.actions[1].user_id)
def testMultipleCaseBlocks(self): """ How do we do when submitting a form with multiple blocks for the same case? """ self.assertEqual( 0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "multiple_case_blocks.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) # before the bug was fixed this call failed process_cases(form) case = CommCareCase.get(form.xpath("form/comunidad/case/@case_id")) self.assertEqual('1630005', case.community_code) self.assertEqual('SantaMariaCahabon', case.district_name) self.assertEqual('TAMERLO', case.community_name) ids = case.get_xform_ids_from_couch() self.assertEqual(1, len(ids)) self.assertEqual(form._id, ids[0])