def test_update_bad_field():
    os.environ[
        'TOOLKIT_CONFIG_NAME'] = '../dunetoolkit/toolkit_config_test.json'

    # set up database to be updated
    teardown_db_for_test()
    db_obj = set_up_db_for_test()

    # perform update
    doc_id = '000000000000000000000002'
    doc = search_by_id(doc_id)
    new_doc_id, error_msg = update(doc_id, remove_doc=False, \
        update_pairs={'bad_field':'val'}, \
        new_meas_objects=[], \
        meas_remove_indices=[] \
    )
    assert new_doc_id == None

    # test that doc did not get transferred
    oldversion_doc = search_by_id(doc_id, coll_type='old_versions')
    assert oldversion_doc == None

    #test that currversion doc was not inserted
    all_docs = query_for_all_docs()
    for doc in all_docs:
        assert 'bad_field' not in list(doc.keys())
def test_update_new_meas_objects_str_for_val_b():
    os.environ[
        'TOOLKIT_CONFIG_NAME'] = '../dunetoolkit/toolkit_config_test.json'

    # set up database to be updated
    teardown_db_for_test()
    db_obj = set_up_db_for_test()

    new_meas_objects = [{
        'isotope': 'U-235',
        'type': 'range',
        'unit': 'g',
        'value': ['a', 'b']
    }]
    doc_id = '000000000000000000000002'
    orig_doc = search_by_id(doc_id)
    new_doc_id, error_msg = update(doc_id,
                                   remove_doc=False,
                                   new_meas_objects=new_meas_objects)
    assert new_doc_id == None

    # test that doc got transferred
    oldversion_doc = search_by_id(doc_id, coll_type='old_versions')
    assert oldversion_doc == None

    # test no change to original doc
    new_doc = search_by_id(doc_id)
    assert len(new_doc['measurement']['results']) == len(
        orig_doc['measurement']['results'])
def test_update_new_meas_objects():
    os.environ[
        'TOOLKIT_CONFIG_NAME'] = '../dunetoolkit/toolkit_config_test.json'

    # set up database to be updated
    teardown_db_for_test()
    db_obj = set_up_db_for_test()

    new_meas_objects = [{
        'isotope': 'K-40',
        'type': 'measurement',
        'unit': 'g/cm',
        'value': [0.2]
    }, {
        'isotope': 'U-235',
        'type': 'range',
        'unit': 'g',
        'value': [0.3, 2.1]
    }]
    doc_id = '000000000000000000000002'
    orig_doc = search_by_id(doc_id)
    new_doc_id, error_msg = update(doc_id,
                                   remove_doc=False,
                                   new_meas_objects=new_meas_objects)
    assert new_doc_id != None
    new_doc_id = str(new_doc_id)

    # test that doc got transferred
    oldversion_doc = search_by_id(doc_id, coll_type='old_versions')
    assert oldversion_doc == orig_doc

    # test new (current version) doc
    new_doc = search_by_id(new_doc_id)

    # test version num
    orig_doc.pop('_version')
    new_version = new_doc.pop('_version')
    assert new_version == 2

    # test parent id
    orig_doc.pop('_id')
    parent_id = new_doc.pop('_parent_id')
    assert parent_id == doc_id

    # test id once more
    new_version_doc_id = str(new_doc.pop('_id'))
    assert new_doc_id == new_version_doc_id

    # test orig doc and curr version doc equality
    len_orig_meas_results = len(orig_doc['measurement'].pop('results'))
    assert new_doc['measurement'].pop(
        'results')[len_orig_meas_results:] == new_meas_objects
    assert orig_doc == new_doc
def test_update_remove_doc():
    os.environ[
        'TOOLKIT_CONFIG_NAME'] = '../dunetoolkit/toolkit_config_test.json'

    # set up database to be updated
    teardown_db_for_test()
    db_obj = set_up_db_for_test()

    # perform update
    doc_id = '000000000000000000000002'
    doc = search_by_id(doc_id)  #, db_obj=db_obj)
    new_doc_id, error_msg = update(doc_id, remove_doc=True)  #, db_obj=db_obj)
    assert new_doc_id == None

    oldversion_doc = search_by_id(doc_id, coll_type='old_versions')
    assert doc == oldversion_doc
def perform_update(doc_id, remove_doc, update_pairs, meas_remove_indices, meas_add_eles, db_obj, is_assay_request_update=False, is_assay_request_verify=False):
    """This function calls the dunetoolkit update function with the update fields and values parsed from the form data.

    args:
        * doc_id (str): the ID of the document to update, extracted from the form data.
        * remove_doc (bool): whether to remove the entire document from the database (if True).
        * update_pairs (dict): a set of (non-measurement results) fields and corresponding values to update in the document in the database.
        * meas_remove_indices (list of int): the integer indices of measurement results objects to remove entirely from the measurement results field.
        * meas_add_eles (list of dict): the new measurement results objects to add to the measurement results field.
        * db_obj (pymongo.database.Database): a pymongo database object that, once a collection has been selected, can be used to query.
        * is_assay_request_update (bool): whether the document to update is an assay (in the "assays" collection) or an assay request (in the "assay_requests" collection).

    returns:
        * bson.objectid.ObjectId. The ID of the document that was just updated (if successful).
        * str. An error message (if an error happened).
    """
    new_doc_id, error_msg = update(doc_id, db_obj, remove_doc, update_pairs, meas_add_eles, meas_remove_indices, is_assay_request_update=is_assay_request_update, is_assay_request_verify=is_assay_request_verify)
    return new_doc_id, error_msg
def test_update_meas_remove_indices():
    os.environ[
        'TOOLKIT_CONFIG_NAME'] = '../dunetoolkit/toolkit_config_test.json'

    # set up database to be updated
    teardown_db_for_test()
    db_obj = set_up_db_for_test()

    remove_indices = [0, 2]  # list len is 3
    doc_id = '000000000000000000000002'
    orig_doc = search_by_id(doc_id, db_obj=db_obj)
    new_doc_id, error_msg = update(doc_id,
                                   remove_doc=False,
                                   meas_remove_indices=remove_indices)
    assert new_doc_id != None
    new_doc_id = str(new_doc_id)

    # test that doc got transferred
    oldversion_doc = search_by_id(doc_id, coll_type='old_versions')
    assert oldversion_doc == orig_doc

    # test new (current version) doc
    new_doc = search_by_id(new_doc_id)

    # test version num
    orig_doc.pop('_version')
    new_version = new_doc.pop('_version')
    assert new_version == 2

    # test parent id
    orig_doc.pop('_id')
    parent_id = new_doc.pop('_parent_id')
    assert parent_id == doc_id

    # test id once more
    new_version_doc_id = str(new_doc.pop('_id'))
    assert new_doc_id == new_version_doc_id

    # test orig doc and curr version doc equality
    orig_meas_results = orig_doc['measurement'].pop('results')
    new_meas_results = new_doc['measurement'].pop('results')
    assert len(new_meas_results) == 1
    assert new_meas_results[0] == orig_meas_results[1]
    assert orig_doc == new_doc
def test_update_nochange():
    os.environ[
        'TOOLKIT_CONFIG_NAME'] = '../dunetoolkit/toolkit_config_test.json'

    # set up database to be updated
    teardown_db_for_test()
    db_obj = set_up_db_for_test()

    # perform update
    doc_id = '000000000000000000000002'
    doc = search_by_id(doc_id)  #, db_obj=db_obj)
    new_doc_id, error_msg = update(doc_id, remove_doc=False, \
        update_pairs={}, \
        new_meas_objects=[], \
        meas_remove_indices=[] \
    )
    assert new_doc_id != None
    assert type(new_doc_id) is ObjectId
    new_doc_id = str(new_doc_id)

    # test value in oldversion database
    oldversion_doc = search_by_id(doc_id, coll_type='old_versions')
    assert doc == oldversion_doc

    # test currversion doc
    currversion_doc = search_by_id(new_doc_id)  #, db_obj=db_obj)

    # test version num
    doc.pop('_version')
    new_version = currversion_doc.pop('_version')
    assert new_version == 2

    # test parent id
    doc.pop('_id')
    parent_id = currversion_doc.pop('_parent_id')
    assert parent_id == doc_id

    # test id once more
    new_version_doc_id = str(currversion_doc.pop('_id'))
    assert new_doc_id == new_version_doc_id

    # test orig doc and curr version doc equality
    assert doc == currversion_doc
def test_update_meas_remove_indices_bad_idx():
    os.environ[
        'TOOLKIT_CONFIG_NAME'] = '../dunetoolkit/toolkit_config_test.json'

    # set up database to be updated
    teardown_db_for_test()
    db_obj = set_up_db_for_test()

    remove_indices = [4]  # list len is 3
    doc_id = '000000000000000000000002'
    orig_doc = search_by_id(doc_id)
    new_doc_id, error_msg = update(doc_id,
                                   remove_doc=False,
                                   meas_remove_indices=remove_indices)
    assert new_doc_id == None

    # test that doc did not get transferred
    oldversion_doc = search_by_id(doc_id, coll_type='old_versions')
    assert oldversion_doc == None

    # test no change to original doc
    new_doc = search_by_id(doc_id)
    assert len(new_doc['measurement']['results']) == len(
        orig_doc['measurement']['results'])
def test_update_all():
    os.environ[
        'TOOLKIT_CONFIG_NAME'] = '../dunetoolkit/toolkit_config_test.json'

    # set up database to be updated
    teardown_db_for_test()
    db_obj = set_up_db_for_test()

    update_pairs = {
        'grouping': 'new test value',
        'data_source.input.contact': '*****@*****.**',
        'measurement.results.0.unit': 'g',
        'measurement.date': ['2020-10-21']
    }
    new_meas_objects = [{
        'isotope': 'K-40',
        'type': 'measurement',
        'unit': 'g/cm',
        'value': [0.2]
    }, {
        'isotope': 'U-235',
        'type': 'range',
        'unit': 'g',
        'value': [0.3, 2.1]
    }]
    remove_indices = [1, 2]
    doc_id = '000000000000000000000002'
    orig_doc = search_by_id(doc_id)
    new_doc_id, error_msg = update(doc_id,
                                   remove_doc=False,
                                   update_pairs=update_pairs,
                                   new_meas_objects=new_meas_objects,
                                   meas_remove_indices=remove_indices)
    assert new_doc_id != None
    new_doc_id = str(new_doc_id)

    # test that doc got transferred
    oldversion_doc = search_by_id(doc_id, coll_type='old_versions')
    assert oldversion_doc == orig_doc

    # test new (current version) doc
    new_doc = search_by_id(new_doc_id)

    # test version num
    orig_doc.pop('_version')
    new_version = new_doc.pop('_version')
    assert new_version == 2

    # test parent id
    orig_doc.pop('_id')
    parent_id = new_doc.pop('_parent_id')
    assert parent_id == doc_id

    # test id once more
    new_version_doc_id = str(new_doc.pop('_id'))
    assert new_doc_id == new_version_doc_id

    # correct the date values to be datetime objects now, not strings
    for update_key in ['measurement.date', 'data_source.input.date']:
        if update_key in list(update_pairs.keys()):
            for i in range(len(update_pairs[update_key])):
                update_pairs[update_key][i] = convert_str_to_date(
                    update_pairs[update_key][i])

    # test orig doc and curr version doc equality
    for update_key in update_pairs:
        new_val = update_pairs[update_key]
        key_parts = update_key.split('.')
        if len(key_parts) == 1:
            orig_doc.pop(key_parts[0])
            assert new_doc.pop(key_parts[0]) == new_val
        elif len(key_parts) == 2:
            orig_doc[key_parts[0]].pop(key_parts[1])
            assert new_doc[key_parts[0]].pop(key_parts[1]) == new_val
        elif len(key_parts) == 3:
            orig_doc[key_parts[0]][key_parts[1]].pop(key_parts[2])
            assert new_doc[key_parts[0]][key_parts[1]].pop(
                key_parts[2]) == new_val
        elif len(key_parts) == 4:
            try:
                key_parts_2 = int(key_parts[2])
            except:
                key_parts_2 = key_parts[2]
            orig_doc[key_parts[0]][key_parts[1]][key_parts_2].pop(key_parts[3])
            assert new_doc[key_parts[0]][key_parts[1]][key_parts_2].pop(
                key_parts[3]) == new_val
        else:
            assert 0 == 1

    orig_meas = orig_doc['measurement'].pop('results')
    meas_eles = new_doc['measurement'].pop('results')
    for new_meas in new_meas_objects:
        assert new_meas in meas_eles
    for removed_meas in [orig_meas[1], orig_meas[2]]:
        assert removed_meas not in meas_eles

    assert orig_doc == new_doc
def test_update_update_pairs_update_twice():
    os.environ[
        'TOOLKIT_CONFIG_NAME'] = '../dunetoolkit/toolkit_config_test.json'

    # set up database to be updated
    teardown_db_for_test()
    db_obj = set_up_db_for_test()

    # PERFORM AND TEST FIRST UPDATE
    u1_doc_id = '000000000000000000000002'
    u1_doc = search_by_id(u1_doc_id)
    u1_update_pairs = {
        'grouping': 'new test value',
        'data_source.input.contact': '*****@*****.**',
        'measurement.results.0.unit': 'g',
        'measurement.date': ['2020-10-21']
    }
    u1_new_doc_id, u1_error_msg = update(u1_doc_id, remove_doc=False, \
        update_pairs=u1_update_pairs, \
        new_meas_objects=[], \
        meas_remove_indices=[] \
    )
    assert u1_new_doc_id != None
    u1_new_doc_id = str(u1_new_doc_id)

    # test value in oldversion database
    u1_oldversion_doc = search_by_id(u1_doc_id, coll_type='old_versions')
    assert (u1_doc == u1_oldversion_doc)

    # test new (current version) doc
    u1_new_doc = search_by_id(u1_new_doc_id)

    # test version num
    u1_doc.pop('_version')
    u1_new_version = u1_new_doc.pop('_version')
    assert u1_new_version == 2

    # test parent id
    u1_doc.pop('_id')
    u1_parent_id = u1_new_doc.pop('_parent_id')
    assert u1_parent_id == u1_doc_id

    # test id once more
    u1_new_version_doc_id = str(u1_new_doc.pop('_id'))
    assert u1_new_doc_id == u1_new_version_doc_id

    # test orig doc and curr version doc equality
    u1_doc.pop('grouping')
    u1_doc['data_source']['input'].pop('contact')
    u1_doc['measurement']['results'][0].pop('unit')
    u1_doc['measurement'].pop('date')
    assert u1_new_doc.pop('grouping') == 'new test value'
    assert u1_new_doc['data_source']['input'].pop(
        'contact') == '*****@*****.**'
    assert u1_new_doc['measurement']['results'][0].pop('unit') == 'g'
    assert u1_new_doc['measurement'].pop('date') == [
        datetime.datetime(2020, 10, 21)
    ]
    assert u1_doc == u1_new_doc

    # PERFORM AND TEST SECOND UPDATE
    u2_doc_id = u1_new_version_doc_id
    u2_doc = search_by_id(u2_doc_id)
    u2_update_pairs = {'grouping': 'test value two'}
    u2_new_doc_id, u2_error_msg = update(u2_doc_id,
                                         remove_doc=False,
                                         update_pairs=u2_update_pairs)
    assert u2_new_doc_id != None
    u2_new_doc_id = str(u2_new_doc_id)

    u2_oldversion_doc = search_by_id(u2_doc_id, coll_type='old_versions')
    assert u2_doc == u2_oldversion_doc

    u2_new_doc = search_by_id(u2_new_doc_id)

    u2_doc.pop('_version')
    u2_new_version = u2_new_doc.pop('_version')
    assert u2_new_version == 3

    u2_doc.pop('_id')
    u2_parent_id = u2_new_doc.pop('_parent_id')
    assert u2_parent_id == u2_doc_id

    u2_new_doc.pop('_id')
    u2_doc.pop('grouping')
    assert u2_new_doc.pop('grouping') == 'test value two'
def test_update_update_pairs_all():
    os.environ[
        'TOOLKIT_CONFIG_NAME'] = '../dunetoolkit/toolkit_config_test.json'

    # set up database to be updated
    teardown_db_for_test()
    db_obj = set_up_db_for_test()

    # perform update
    doc_id = '000000000000000000000002'
    doc = search_by_id(doc_id)
    update_pairs = {
        'grouping': 'new test value',
        'sample.name': 'testing sample name',
        'sample.description': 'test descrip',
        'sample.source': 'example src',
        'sample.id': '123456test',
        'sample.owner.name': 'test',
        'sample.owner.contact': '*****@*****.**',
        'measurement.results.0.isotope': 'K-40',
        'measurement.results.0.type': 'range',
        'measurement.results.0.unit': 'g',
        'measurement.results.0.value': [10.3, 12.9],
        'measurement.practitioner.name': 'tester',
        'measurement.practitioner.contact': '*****@*****.**',
        'measurement.technique': 'test',
        'measurement.institution': 'test place',
        'measurement.date': ['2020-10-21'],
        'measurement.description': 'test descrip',
        'measurement.requestor.name': 'test requestor',
        'measurement.requestor.contact': '*****@*****.**',
        'data_source.reference': 'testing',
        'data_source.input.name': 'testing',
        'data_source.input.contact': '*****@*****.**',
        'data_source.input.date': ['2010/18/02', '2020-10-21'],
        'data_source.input.notes': 'test test test',
    }
    new_doc_id, error_msg = update(doc_id, remove_doc=False, \
        update_pairs=update_pairs, \
        new_meas_objects=[], \
        meas_remove_indices=[] \
    )
    assert new_doc_id != None
    new_doc_id = str(new_doc_id)

    # test value in oldversion database
    oldversion_doc = search_by_id(doc_id, coll_type='old_versions')
    assert (doc == oldversion_doc)

    # test currversion doc
    currversion_doc = search_by_id(new_doc_id)

    # test version num
    doc.pop('_version')
    new_version = currversion_doc.pop('_version')
    assert new_version == 2

    # test parent id
    doc.pop('_id')
    parent_id = currversion_doc.pop('_parent_id')
    assert parent_id == doc_id

    # test id once more
    new_version_doc_id = str(currversion_doc.pop('_id'))
    assert new_doc_id == new_version_doc_id

    # correct the date values to be datetime objects now, not strings
    for update_key in ['measurement.date', 'data_source.input.date']:
        for i in range(len(update_pairs[update_key])):
            update_pairs[update_key][i] = convert_str_to_date(
                update_pairs[update_key][i])

    # test orig doc and curr version doc equality
    for update_key in update_pairs:
        new_val = update_pairs[update_key]
        key_parts = update_key.split('.')

        if len(key_parts) == 1:
            doc.pop(key_parts[0])
            assert currversion_doc.pop(key_parts[0]) == new_val
        elif len(key_parts) == 2:
            doc[key_parts[0]].pop(key_parts[1])
            assert currversion_doc[key_parts[0]].pop(key_parts[1]) == new_val
        elif len(key_parts) == 3:
            doc[key_parts[0]][key_parts[1]].pop(key_parts[2])
            assert currversion_doc[key_parts[0]][key_parts[1]].pop(
                key_parts[2]) == new_val
        elif len(key_parts) == 4:
            try:
                key_parts_2 = int(key_parts[2])
            except:
                key_parts_2 = key_parts[2]
            doc[key_parts[0]][key_parts[1]][key_parts_2].pop(key_parts[3])
            assert currversion_doc[key_parts[0]][
                key_parts[1]][key_parts_2].pop(key_parts[3]) == new_val
        else:
            assert 0 == 1