def test_02_request(self): # Check we can instantiate and work with a Request # first make a blank one req = Request() # now make one around the fixture source = RequestFixtureFactory.example() req = Request(source) # make one with a broken source broken = {"whatever" : "broken"} with self.assertRaises(dataobj.DataStructureException): req = Request(broken) # now make one bit by bit req = Request() req.record = source.get("record") req.owner = "test1" req.action = "update" req.public_id = "abcdefg" assert req.owner == "test1" assert req.action == "update" assert req.public_id == "abcdefg" # now make it broken req = Request() with self.assertRaises(dataobj.DataStructureException): req.record = {"random" : "stuff"}
def delete(cls, record, account, public_id=None): """ Record a "delete" request, with the associated (minimal) record data, requested by the given account Delete requests need only come with enough record data to identify the public record :param record: The mimimal record data for identifying the record :param account: the account to carry out the request on behalf of :param public_id: the public id of a public record for which this is a delete request :return: the Request object that was created """ if record is None: raise RequestAPIException("You can't call 'delete' with a NoneType record argument") if account is None: raise RequestAPIException("You can't call 'delete' with a NoneType account argument") req = Request() req.record = record req.owner = account.id req.action = "delete" if public_id is not None: req.public_id = public_id req.save() return req
def test_11_process_requests_exception(self): # What happens when the process_reuests method fails for a variety of reasons sources = RequestFixtureFactory.request_per_day("2001-01", 9) dois = ["10.1234/first", "10.1234/second", "10.1234/third"] # we're going to construct a series of requests for each doi # starting with a create, then an update, followed by a delete # (not that it matters, as we're going to pump them through a mock) for i in range(len(sources)): s = sources[i] doi_idx = i % 3 # iterate over the dois 3 times doi = dois[doi_idx] s["record"]["dc:identifier"] = [{"type": "doi", "id": doi}] if i < 3: s["record"]["dc:title"] = "Create" req = Request(s) req.action = "update" req.save() elif i < 6: s["record"]["dc:title"] = "Update" req = Request(s) req.action = "update" req.save() else: s["record"]["dc:title"] = "Delete" req = Request(s) req.action = "delete" req.save() time.sleep(2) # set up the mocks PublicApi.publish = publish_mock PublicApi.remove = delete_mock # now run the process job back to the first day with self.assertRaises(TestException): WorkflowApi.process_requests() # we know this died during the 6th update request being processed, # so just check that the workflow state reflects that wfs_dao = WorkflowState() wfs = wfs_dao.pull("requests") assert wfs.last_request == "2001-01-05T00:00:00Z" assert len(wfs.already_processed) == 1
def test_05_request_dao(self): # Check the DAO methods on the Request object dao = Request() source = RequestFixtureFactory.example() req = Request(source) req.owner = "test1" req.action = "update" req.public_id = "abcdefg" req.save(blocking=True) req2 = dao.pull(req.id) assert req2 is not None # check successful queries for identifiers res = dao.find_by_identifier("doi", "10.1234/me", "test1") assert len(res) == 1 res = dao.find_by_identifier("pmcid", "PMC1234", "test1") assert len(res) == 1 res = dao.find_by_identifier("pmid", "87654321", "test1") assert len(res) == 1 res = dao.find_by_identifier("url", "http://example.com/whatever", "test1") assert len(res) == 1 # check unsuccessful ones res = dao.find_by_identifier("doi", "10.1234/you", "test1") assert len(res) == 0 res = dao.find_by_identifier("pmcid", "PMC5678", "test1") assert len(res) == 0 res = dao.find_by_identifier("pmid", "123456789", "test1") assert len(res) == 0 res = dao.find_by_identifier("url", "http://example.com/this", "test1") assert len(res) == 0 # and check using the wrong owner res = dao.find_by_identifier("doi", "10.1234/me", "test2") assert len(res) == 0 res = dao.find_by_identifier("pmcid", "PMC1234", "test2") assert len(res) == 0 res = dao.find_by_identifier("pmid", "87654321", "test2") assert len(res) == 0 res = dao.find_by_identifier("url", "http://example.com/whatever", "test2") assert len(res) == 0
def update(cls, record, account, public_id=None): """ Record an "update" request, with the associated record data, requested by the given account :param record: The raw dict data (e.g. coming from the web API) which makes up the body of the request :param account: the account to carry out the request on behalf of :param public_id: The public id of a public record for which this is an update :return: the Request object that was created """ if record is None: raise RequestAPIException("You can't call 'update' with a NoneType record argument") if account is None: raise RequestAPIException("You can't call 'update' with a NoneType account argument") req = Request() req.record = record req.owner = account.id req.action = "update" if public_id is not None: req.public_id = public_id req.save() return req
def test_11_process_requests_cycle(self): # Run through the process of processing a Request into a PublicAPC source = RequestFixtureFactory.example() if "id" in source: del source["id"] pub_dao = PublicAPC() wfs_dao = WorkflowState() # first make a record for the first time first = deepcopy(source) del first["record"]["dc:title"] req = Request(first) req.owner = "test" req.action = "update" req.save(blocking=True) # run the job WorkflowApi.process_requests() time.sleep(2) # first check that a public record was made pubs = pub_dao.find_by_doi("10.1234/me") assert len(pubs) == 1 assert pubs[0].record.get("dc:title") is None # check that the workflow state was created wfs = wfs_dao.pull("requests") assert wfs is not None assert wfs.last_request == req.created_date assert wfs.already_processed == [req.id] # now run an update with a different date second = deepcopy(source) second["record"]["dc:title"] = "Update" second["created_date"] = "2002-01-01T00:00:00Z" req2 = Request(second) req2.owner = "test" req2.action = "update" req2.save(blocking=True) # run the job again WorkflowApi.process_requests() time.sleep(2) # check the public record was updated pubs = pub_dao.find_by_doi("10.1234/me") assert len(pubs) == 1 assert pubs[0].record.get("dc:title") == "Update" # check that the workflow state was updated wfs = wfs_dao.pull("requests") assert wfs is not None assert wfs.last_request == req2.created_date assert wfs.already_processed == [req2.id] # now run an update with the same date, to observe the difference in the workflow state third = deepcopy(source) third["record"]["dc:title"] = "Update 2" third["created_date"] = "2002-01-01T00:00:00Z" req3 = Request(third) req3.owner = "test" req3.action = "update" req3.save(blocking=True) # run the job again WorkflowApi.process_requests() time.sleep(2) # check the public record was updated pubs = pub_dao.find_by_doi("10.1234/me") assert len(pubs) == 1 assert ( pubs[0].record.get("dc:title") == "Update 2" ) # should have been updated, as there are only apc contributions from one source # check that the workflow state was updated wfs = wfs_dao.pull("requests") assert wfs is not None assert wfs.last_request == req3.created_date assert wfs.already_processed == [req2.id, req3.id] # processed records should have been appended # finally issue a delete request fourth = deepcopy(source) fourth["created_date"] = "2003-01-01T00:00:00Z" req4 = Request(fourth) req4.owner = "test" req4.action = "delete" req4.save(blocking=True) # run the job again WorkflowApi.process_requests() time.sleep(2) # check the public record was updated pubs = pub_dao.find_by_doi("10.1234/me") assert len(pubs) == 0 # check that the workflow state was updated wfs = wfs_dao.pull("requests") assert wfs is not None assert wfs.last_request == req4.created_date assert wfs.already_processed == [req4.id] # processed records should have been appended