def test_datastore_basic(self): data_store = CouchDB_DataStore(datastore_name='ion_test_ds', profile=DataStore.DS_PROFILE.RESOURCES) self.data_store = data_store self.resources = {} # Just in case previous run failed without cleaning up, # delete data store data_store.delete_datastore() # Create should succeed and not throw error data_store.create_datastore() # Create should throw exception the second time with self.assertRaises(BadRequest): data_store.create_datastore() # Call ops with wrong object type and make sure exception is thrown with self.assertRaises(BadRequest): data_store.create({"foo": "bar"}) with self.assertRaises(BadRequest): data_store.create_mult([{"foo": "bar"}]) with self.assertRaises(BadRequest): data_store.read({"foo": "bar"}) with self.assertRaises(BadRequest): data_store.read_mult([{"foo": "bar"}]) with self.assertRaises(BadRequest): data_store.update({"foo": "bar"}) with self.assertRaises(BadRequest): data_store.delete({"foo": "bar"}) # Should see new data self.assertIn('ion_test_ds', data_store.list_datastores()) # Something should be returned self.assertTrue(data_store.info_datastore() is not None) res = data_store.list_objects() numcoredocs = len(res) # Construct user role objects admin_role = { "name":"Admin", "description":"Super user" } admin_role_obj = IonObject('UserRole', admin_role) admin_role_tuple = data_store.create(admin_role_obj) self.assertTrue(len(admin_role_tuple) == 2) admin_role_ooi_id = admin_role_tuple[0] data_provider_role = { "name":"Data Provider", "description":"User allowed to ingest data sets" } data_provider_role_obj = IonObject('UserRole', data_provider_role) data_provider_role_tuple = data_store.create(data_provider_role_obj) self.assertTrue(len(data_provider_role_tuple) == 2) data_provider_role_ooi_id = data_provider_role_tuple[0] marine_operator_role = { "name":"Marine Operator", "description":"User allowed to administer instruments" } marine_operator_role_obj = IonObject('UserRole', marine_operator_role) marine_operator_role_tuple = data_store.create(marine_operator_role_obj) self.assertTrue(len(marine_operator_role_tuple) == 2) marine_operator_role_ooi_id = marine_operator_role_tuple[0] role_objs = data_store.read_mult([admin_role_ooi_id, data_provider_role_ooi_id, marine_operator_role_ooi_id]) self.assertTrue(len(role_objs) == 3) self.assertTrue(role_objs[0]._id == admin_role_ooi_id) self.assertTrue(role_objs[1]._id == data_provider_role_ooi_id) self.assertTrue(role_objs[2]._id == marine_operator_role_ooi_id) # Construct three user info objects and assign them roles hvl_contact_info = { "individual_names_given": "Heitor Villa-Lobos", "email": "*****@*****.**", "variables": [ {"name": "Claim To Fame", "value": "Legendary Brazilian composer"} ] } hvl_contact_info_obj = IonObject('ContactInformation', hvl_contact_info) hvl_user_info = { "name": "Heitor Villa-Lobos", "contact": hvl_contact_info_obj } hvl_user_info_obj = IonObject('UserInfo', hvl_user_info) hvl_user_info_tuple = data_store.create(hvl_user_info_obj) self.assertTrue(len(hvl_user_info_tuple) == 2) heitor_villa_lobos_ooi_id = hvl_user_info_tuple[0] ats_contact_info = { "individual_names_given": "Andres Torres Segovia", "email": "*****@*****.**", "variables": [ {"name": "Claim To Fame", "value": "Legendary Concert Guitarist"} ] } ats_contact_info_obj = IonObject('ContactInformation', ats_contact_info) ats_user_info = { "name": "Andres Torres Segovia", "contact": ats_contact_info_obj } ats_user_info_obj = IonObject('UserInfo', ats_user_info) ats_user_info_tuple = data_store.create(ats_user_info_obj) self.assertTrue(len(ats_user_info_tuple) == 2) pok_contact_info = { "individual_names_given": "Per-Olov Kindgren", "email": "*****@*****.**", "variables": [ {"name": "Claim To Fame", "value": "Composer and YouTube star"} ] } pok_contact_info_obj = IonObject('ContactInformation', pok_contact_info) pok_user_info = { "name": "Per-Olov Kindgren", "contact": pok_contact_info_obj } pok_user_info_obj = IonObject('UserInfo', pok_user_info) pok_user_info_tuple = data_store.create(pok_user_info_obj) self.assertTrue(len(pok_user_info_tuple) == 2) # List all objects in data store and confirm there are six docs res = data_store.list_objects() # There are indices. Therefore can't could all docs self.assertTrue(len(res) == 6 + numcoredocs) # Create an Ion object with default values set (if any) data_set = IonObject('Dataset') self.assertTrue(isinstance(data_set, interface.objects.Dataset)) # Assign values to object fields data_set.description = "Real-time water data for Choptank River near Greensboro, MD" # Write Dataset object" write_tuple_1 = data_store.create(data_set) self.assertTrue(len(write_tuple_1) == 2) # Save off the object UUID data_set_uuid = write_tuple_1[0] # Read back the HEAD version of the object and validate fields data_set_read_obj = data_store.read(data_set_uuid) self.assertTrue(data_set_read_obj._id == data_set_uuid) self.assertTrue(isinstance(data_set_read_obj, interface.objects.Dataset)) self.assertTrue(data_set_read_obj.description == "Real-time water data for Choptank River near Greensboro, MD") self.assertTrue('type_' in data_set_read_obj) # Update Dataset's Description field and write data_set_read_obj.description = "Updated Description" write_tuple_2 = data_store.update(data_set_read_obj) self.assertTrue(len(write_tuple_2) == 2) # Retrieve the updated Dataset data_set_read_obj_2 = data_store.read(data_set_uuid) self.assertTrue(data_set_read_obj_2._id == data_set_uuid) self.assertTrue(data_set_read_obj_2.description == "Updated Description") # List all the revisions of Dataset in data store, should be two res = data_store.list_object_revisions(data_set_uuid) self.assertTrue(len(res) == 2) # Do another update to the object data_set_read_obj_2.description = "USGS instantaneous value data for station 01491000" write_tuple_3 = data_store.update(data_set_read_obj_2) # List revisions of Dataset in data store, should now be three res = data_store.list_object_revisions(data_set_uuid) self.assertTrue(len(res) == 3) # Retrieve original version of Dataset obj1 = data_store.read(data_set_uuid, rev_id=write_tuple_1[1]) self.assertTrue(obj1._id == data_set_uuid) self.assertTrue(obj1.description == "Real-time water data for Choptank River near Greensboro, MD") # Retrieve second version of Dataset obj2 = data_store.read(data_set_uuid, rev_id=write_tuple_2[1]) self.assertTrue(obj2._id == data_set_uuid) self.assertTrue(obj2.description == "Updated Description") # Retrieve third version of Dataset obj3 = data_store.read(data_set_uuid, rev_id=write_tuple_3[1]) self.assertTrue(obj3._id == data_set_uuid) self.assertTrue(obj3.description == "USGS instantaneous value data for station 01491000") # Retrieve HEAD version of Dataset head = data_store.read(data_set_uuid) self.assertTrue(head._id == data_set_uuid) self.assertTrue(head.description == "USGS instantaneous value data for station 01491000") # Delete Dataset by object id data_store.delete(head) # Try to re-delete Dataset by object id. Should throw exception. with self.assertRaises(NotFound): data_store.delete(head._id) # List all objects in data store, should be back to six res = data_store.list_objects() self.assertTrue(len(res) == 6 + numcoredocs) # List revisions of now deleted Dataset, should be empty list res = data_store.list_object_revisions(data_set_uuid) self.assertTrue(len(res) == 0) o1 = IonObject("Dataset", name="One more") o2 = IonObject("Dataset", name="Another one") res = data_store.create_mult((o1, o2)) self.assertTrue(all([success for success, oid, rev in res])) res = data_store.list_objects() self.assertTrue(len(res) == 8 + numcoredocs) # Delete data store to clean up data_store.delete_datastore() # Assert data store is now gone self.assertNotIn('ion_test_ds', data_store.list_datastores())
def test_datastore_attach(self): data_store = CouchDB_DataStore(datastore_name='ion_test_ds', profile=DataStore.DS_PROFILE.RESOURCES) self.data_store = data_store self.resources = {} # Create an Ion object with default values set (if any) data_set = IonObject('Dataset') self.assertTrue(isinstance(data_set, interface.objects.Dataset)) # Assign values to object fields data_set.description = "Real-time water data for Choptank River near Greensboro, MD" # Write Dataset object" write_tuple_1 = data_store.create(data_set) # Save off the object UUID data_set_uuid = write_tuple_1[0] # Read back the HEAD version of the object data_set_read_obj = data_store.read(data_set_uuid) # Update Dataset's Description field and write data_set_read_obj.description = "Updated Description" write_tuple_2 = data_store.update(data_set_read_obj) # test attachment related stuff # create attachment ds_id_and_rev = {} attachment_name = 'resource.attachment' ds_id_and_rev['_id'] = write_tuple_2[0] ds_id_and_rev['_rev'] = write_tuple_2[1] data = "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x03\x00\x00\x00(-\x0fS\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\x00~PLTEf3\x00\xfc\xf7\xe0\xee\xcc\x00\xd3\xa0\x00\xcc\x99\x00\xec\xcdc\x9fl\x00\xdd\xb2\x00\xff\xff\xff|I\x00\xf9\xdb\x00\xdd\xb5\x19\xd9\xad\x10\xb6\x83\x00\xf8\xd6\x00\xf2\xc5\x00\xd8\xab\x00n;\x00\xff\xcc\x00\xd6\xa4\t\xeb\xb8\x00\x83Q\x00\xadz\x00\xff\xde\x00\xff\xd6\x00\xd6\xa3\x00\xdf\xaf\x00\xde\xad\x10\xbc\x8e\x00\xec\xbe\x00\xec\xd4d\xff\xe3\x00tA\x00\xf6\xc4\x00\xf6\xce\x00\xa5u\x00\xde\xa5\x00\xf7\xbd\x00\xd6\xad\x08\xdd\xaf\x19\x8cR\x00\xea\xb7\x00\xee\xe9\xdf\xc5\x00\x00\x00\tpHYs\x00\x00\n\xf0\x00\x00\n\xf0\x01B\xac4\x98\x00\x00\x00\x1ctEXtSoftware\x00Adobe Fireworks CS4\x06\xb2\xd3\xa0\x00\x00\x00\x15tEXtCreation Time\x0029/4/09Oq\xfdE\x00\x00\x00\xadIDAT\x18\x95M\x8f\x8d\x0e\x820\x0c\x84;ZdC~f\x07\xb2\x11D\x86\x89\xe8\xfb\xbf\xa0+h\xe2\x97\\\xd2^\x93\xb6\x07:1\x9f)q\x9e\xa5\x06\xad\xd5\x13\x8b\xac,\xb3\x02\x9d\x12C\xa1-\xef;M\x08*\x19\xce\x0e?\x1a\xeb4\xcc\xd4\x0c\x831\x87V\xca\xa1\x1a\xd3\x08@\xe4\xbd\xb7\x15P;\xc8\xd4{\x91\xbf\x11\x90\xffg\xdd\x8di\xfa\xb6\x0bs2Z\xff\xe8yg2\xdc\x11T\x96\xc7\x05\xa5\xef\x96+\xa7\xa59E\xae\xe1\x84cm^1\xa6\xb3\xda\x85\xc8\xd8/\x17se\x0eN^'\x8c\xc7\x8e\x88\xa8\xf6p\x8e\xc2;\xc6.\xd0\x11.\x91o\x12\x7f\xcb\xa5\xfe\x00\x89]\x10:\xf5\x00\x0e\xbf\x00\x00\x00\x00IEND\xaeB`\x82" some_text = "SOME TEXT" # create attachment with no data with self.assertRaises(BadRequest): data_store.create_attachment(doc=ds_id_and_rev, data=None, attachment_name=attachment_name, content_type=None, datastore_name="") # create attachment with no attachment with self.assertRaises(BadRequest): data_store.create_attachment(doc=ds_id_and_rev, data=data, attachment_name=None, content_type=None, datastore_name="") #create attachment by passing a doc parameter that # is a dictionary containing _rev and _id elements data_store.create_attachment(doc=ds_id_and_rev, data=data, attachment_name=attachment_name, content_type=None, datastore_name="") # read attachment by passing a doc parameter that is a dictionary # containing _rev and _id elements and verify that the content read # is same as the content put in content_read = data_store.read_attachment(doc=ds_id_and_rev, attachment_name=attachment_name, datastore_name="") self.assertEquals(data, content_read) # update attachment by passing a doc parameter that is a dictionary # containing _rev and _id elements data_store.update_attachment(ds_id_and_rev, attachment_name, data=some_text) # read the attachment passing only the doc _id and verify that content has changed content_read = data_store.read_attachment(doc=ds_id_and_rev['_id'], attachment_name=attachment_name, datastore_name="") self.assertNotEquals(data, content_read) self.assertEquals(some_text, content_read) # delete attachment by passing a doc parameter that is a dictionary containing _rev # and _id elements data_store.delete_attachment(doc=ds_id_and_rev, attachment_name=attachment_name) # interestingly, deleting an attachment that does not exist works # pass a doc parameter that is a dictionary containing _rev and _id elements data_store.delete_attachment(doc=ds_id_and_rev['_id'], attachment_name='no_such_file') #create attachment by passing a doc parameter that is string indicating _id data_store.create_attachment(doc=ds_id_and_rev['_id'], data=data, attachment_name=attachment_name, content_type=None, datastore_name="") # read attachment by passing a doc parameter that is a string indicating _id # and verify that the content read is same as the content put in content_read = data_store.read_attachment(doc=ds_id_and_rev['_id'], attachment_name=attachment_name, datastore_name="") self.assertEquals(data, content_read) # update attachment by passing a doc parameter that is a string indicating _id data_store.update_attachment(ds_id_and_rev['_id'], attachment_name, data=some_text) # create another attachment and # list attachments by passing a doc parameter that is a dictionary # containing _rev and _id elements data_store.create_attachment(doc=ds_id_and_rev['_id'], data=data, attachment_name=attachment_name+"_01", content_type=None, datastore_name="") _attachments = data_store.list_attachments(doc=ds_id_and_rev) #refer to a previous version of the document updated_ds_id_and_rev = {} updated_ds_id_and_rev['_id'] = write_tuple_1[0] updated_ds_id_and_rev['_rev'] = write_tuple_1[1] # deleting attachment from the previous (wrong) revision raises document update conflict with self.assertRaises(Exception): data_store.delete_attachment(doc=updated_ds_id_and_rev, attachment_name=attachment_name) # operations on previous versions are not allowed with self.assertRaises(Exception): data_store.create_attachment(doc=updated_ds_id_and_rev, data=some_text, attachment_name=attachment_name, content_type=None, datastore_name="") # send in an incorrect document _id with self.assertRaises(NotFound): data_store.create_attachment(doc="incorrect_id", data=data, attachment_name=attachment_name, content_type=None, datastore_name="") # send in an incorrect document _id with self.assertRaises(NotFound): data_store.read_attachment(doc="incorrect_id", attachment_name=attachment_name, datastore_name="") # send in an incorrect attachment_name with self.assertRaises(NotFound): data_store.read_attachment(doc=ds_id_and_rev['_id'], attachment_name="incorrect_attachment", datastore_name="") # send in an incorrect document_id with self.assertRaises(NotFound): data_store.update_attachment(doc="incorrect_id", attachment_name=attachment_name, data=some_text) # send in an incorrect attachment_name; this should work because update creates an # attachment when it can't find an attachment to update data_store.update_attachment(ds_id_and_rev['_id'], attachment_name="incorrect_attachment", data=some_text) # send in an incorrect attachment_name; interestingly, this is not an error data_store.delete_attachment(doc=ds_id_and_rev['_id'], attachment_name='no_such_file') # send in an incorrect document_id with self.assertRaises(NotFound): data_store.delete_attachment(doc="incorrect_id", attachment_name='no_such_file')