diff --git a/qcfractal/qcfractal/components/gridoptimization/test_record_socket.py b/qcfractal/qcfractal/components/gridoptimization/test_record_socket.py index 22f595ac7..896a30ee2 100644 --- a/qcfractal/qcfractal/components/gridoptimization/test_record_socket.py +++ b/qcfractal/qcfractal/components/gridoptimization/test_record_socket.py @@ -176,11 +176,12 @@ def test_gridoptimization_socket_run( meta_1, id_1 = storage_socket.records.gridoptimization.add( [molecules_1], input_spec_1, "test_tag", PriorityEnum.low, "submit_user", "group1", True ) + id_1 = id_1[0] assert meta_1.success time_0 = datetime.utcnow() finished, n_optimizations = run_service( - storage_socket, activated_manager_name, id_1[0], generate_task_key, result_data_1, 100 + storage_socket, activated_manager_name, id_1, generate_task_key, result_data_1, 100 ) time_1 = datetime.utcnow() @@ -196,7 +197,7 @@ def test_gridoptimization_socket_run( assert time_0 < rec.compute_history[-1].modified_on < time_1 assert rec.service is None - desc_info = storage_socket.records.get_short_descriptions(id_1)[0] + desc_info = storage_socket.records.get_short_descriptions([id_1])[0] short_desc = desc_info["description"] assert desc_info["record_type"] == rec.record_type assert desc_info["created_on"] == rec.created_on @@ -213,3 +214,39 @@ def test_gridoptimization_socket_run( for o in rec.optimizations: optr = session.get(OptimizationRecordORM, o.optimization_id) assert optr.energies[-1] == o.energy + + +def test_gridoptimization_socket_run_duplicate( + storage_socket: SQLAlchemySocket, + session: Session, + activated_manager_name: ManagerName, +): + input_spec_1, molecules_1, result_data_1 = load_test_data("go_H2O2_psi4_b3lyp") + + meta_1, id_1 = storage_socket.records.gridoptimization.add( + [molecules_1], input_spec_1, "test_tag", PriorityEnum.low, None, None, True + ) + id_1 = id_1[0] + assert meta_1.success + + run_service(storage_socket, activated_manager_name, id_1, generate_task_key, result_data_1, 100) + + rec_1 = session.get(GridoptimizationRecordORM, id_1) + assert rec_1.status == RecordStatusEnum.complete + opt_ids_1 = [x.optimization_id for x in rec_1.optimizations] + + # Submit again, without duplicate checking + meta_2, id_2 = storage_socket.records.gridoptimization.add( + [molecules_1], input_spec_1, "test_tag", PriorityEnum.low, None, None, False + ) + id_2 = id_2[0] + assert meta_2.success + assert id_2 != id_1 + + run_service(storage_socket, activated_manager_name, id_2, generate_task_key, result_data_1, 1000) + + rec_2 = session.get(GridoptimizationRecordORM, id_2) + assert rec_2.status == RecordStatusEnum.complete + opt_ids_2 = [x.optimization_id for x in rec_2.optimizations] + + assert set(opt_ids_1).isdisjoint(opt_ids_2) diff --git a/qcfractal/qcfractal/components/manybody/test_record_socket.py b/qcfractal/qcfractal/components/manybody/test_record_socket.py index 3a0586499..e1d7c8aa5 100644 --- a/qcfractal/qcfractal/components/manybody/test_record_socket.py +++ b/qcfractal/qcfractal/components/manybody/test_record_socket.py @@ -98,11 +98,12 @@ def test_manybody_socket_run( meta_1, id_1 = storage_socket.records.manybody.add( [molecules_1], input_spec_1, "test_tag", PriorityEnum.low, "submit_user", "group1", True ) + id_1 = id_1[0] assert meta_1.success time_0 = datetime.utcnow() finished, n_singlepoints = run_service( - storage_socket, activated_manager_name, id_1[0], generate_task_key, result_data_1, 100 + storage_socket, activated_manager_name, id_1, generate_task_key, result_data_1, 100 ) time_1 = datetime.utcnow() @@ -118,7 +119,7 @@ def test_manybody_socket_run( assert time_0 < rec.compute_history[-1].modified_on < time_1 assert rec.service is None - desc_info = storage_socket.records.get_short_descriptions(id_1)[0] + desc_info = storage_socket.records.get_short_descriptions([id_1])[0] short_desc = desc_info["description"] assert desc_info["record_type"] == rec.record_type assert desc_info["created_on"] == rec.created_on @@ -130,3 +131,39 @@ def test_manybody_socket_run( assert "All manybody singlepoint computations are complete" in out assert len(rec.clusters) == n_singlepoints + + +def test_manybody_socket_run_duplicate( + storage_socket: SQLAlchemySocket, + session: Session, + activated_manager_name: ManagerName, +): + input_spec_1, molecules_1, result_data_1 = load_test_data("mb_cp_he4_psi4_mp2") + + meta_1, id_1 = storage_socket.records.manybody.add( + [molecules_1], input_spec_1, "test_tag", PriorityEnum.low, None, None, True + ) + id_1 = id_1[0] + assert meta_1.success + + run_service(storage_socket, activated_manager_name, id_1, generate_task_key, result_data_1, 1000) + + rec_1 = session.get(ManybodyRecordORM, id_1) + assert rec_1.status == RecordStatusEnum.complete + sp_ids_1 = [x.singlepoint_id for x in rec_1.clusters] + + # Submit again, without duplicate checking + meta_2, id_2 = storage_socket.records.manybody.add( + [molecules_1], input_spec_1, "test_tag", PriorityEnum.low, None, None, False + ) + id_2 = id_2[0] + assert meta_2.success + assert id_2 != id_1 + + run_service(storage_socket, activated_manager_name, id_2, generate_task_key, result_data_1, 1000) + + rec_2 = session.get(ManybodyRecordORM, id_2) + assert rec_2.status == RecordStatusEnum.complete + sp_ids_2 = [x.singlepoint_id for x in rec_2.clusters] + + assert set(sp_ids_1).isdisjoint(sp_ids_2) diff --git a/qcfractal/qcfractal/components/neb/test_record_socket.py b/qcfractal/qcfractal/components/neb/test_record_socket.py index f841ee34f..073512be9 100644 --- a/qcfractal/qcfractal/components/neb/test_record_socket.py +++ b/qcfractal/qcfractal/components/neb/test_record_socket.py @@ -245,3 +245,41 @@ def test_neb_socket_run( out = rec.compute_history[-1].outputs["stdout"].get_output() assert "NEB calculation is completed" in out + + +def test_neb_socket_run_duplicate( + storage_socket: SQLAlchemySocket, + session: Session, + activated_manager_name: ManagerName, +): + input_spec_1, molecules_1, result_data_1 = load_test_data("neb_HCN_psi4_pbe_opt_diff") + + meta_1, id_1 = storage_socket.records.neb.add( + [molecules_1], input_spec_1, "test_tag", PriorityEnum.low, None, None, True + ) + id_1 = id_1[0] + assert meta_1.success + + run_service(storage_socket, activated_manager_name, id_1, generate_task_key, result_data_1, 100) + + rec_1 = session.get(NEBRecordORM, id_1) + assert rec_1.status == RecordStatusEnum.complete + sp_ids_1 = [x.singlepoint_id for x in rec_1.singlepoints] + opt_ids_1 = [x.optimization_id for x in rec_1.optimizations] + + # Submit again, without duplicate checking + meta_2, id_2 = storage_socket.records.neb.add( + [molecules_1], input_spec_1, "test_tag", PriorityEnum.low, None, None, False + ) + id_2 = id_2[0] + assert meta_2.success + assert id_2 != id_1 + + run_service(storage_socket, activated_manager_name, id_2, generate_task_key, result_data_1, 1000) + + rec_2 = session.get(NEBRecordORM, id_2) + assert rec_2.status == RecordStatusEnum.complete + sp_ids_2 = [x.singlepoint_id for x in rec_2.singlepoints] + opt_ids_2 = [x.optimization_id for x in rec_2.optimizations] + + assert set(sp_ids_1 + opt_ids_1).isdisjoint(sp_ids_2 + opt_ids_2) diff --git a/qcfractal/qcfractal/components/reaction/test_record_socket.py b/qcfractal/qcfractal/components/reaction/test_record_socket.py index c657e3213..9db5c7732 100644 --- a/qcfractal/qcfractal/components/reaction/test_record_socket.py +++ b/qcfractal/qcfractal/components/reaction/test_record_socket.py @@ -6,7 +6,7 @@ import pytest from qcarchivetesting import load_molecule_data -from qcfractal.components.record_db_models import BaseRecordORM +from qcfractal.components.reaction.record_db_models import ReactionRecordORM from qcfractal.db_socket import SQLAlchemySocket from qcfractal.testing_helpers import run_service from qcportal.auth import UserInfo, GroupInfo @@ -34,7 +34,7 @@ def test_reaction_socket_add_get(storage_socket: SQLAlchemySocket, session: Sess time_1 = datetime.utcnow() assert meta.success - recs = [session.get(BaseRecordORM, i) for i in ids] + recs = [session.get(ReactionRecordORM, i) for i in ids] assert len(recs) == 2 for r in recs: @@ -116,17 +116,18 @@ def test_reaction_socket_run( meta_1, id_1 = storage_socket.records.reaction.add( [stoich_1], input_spec_1, "test_tag", PriorityEnum.low, "submit_user", "group1", True ) + id_1 = id_1[0] assert meta_1.success time_0 = datetime.utcnow() finished, n_singlepoints = run_service( - storage_socket, activated_manager_name, id_1[0], generate_task_key, result_data_1, 100 + storage_socket, activated_manager_name, id_1, generate_task_key, result_data_1, 100 ) time_1 = datetime.utcnow() assert finished is True - rec = session.get(BaseRecordORM, id_1) + rec = session.get(ReactionRecordORM, id_1) assert rec.status == RecordStatusEnum.complete assert time_0 < rec.modified_on < time_1 @@ -136,7 +137,7 @@ def test_reaction_socket_run( assert time_0 < rec.compute_history[-1].modified_on < time_1 assert rec.service is None - desc_info = storage_socket.records.get_short_descriptions(id_1)[0] + desc_info = storage_socket.records.get_short_descriptions([id_1])[0] short_desc = desc_info["description"] assert desc_info["record_type"] == rec.record_type assert desc_info["created_on"] == rec.created_on @@ -152,3 +153,41 @@ def test_reaction_socket_run( assert "All reaction components are complete" in out assert rec.total_energy < 0.0 + + +def test_reaction_socket_run_duplicate( + storage_socket: SQLAlchemySocket, + session: Session, + activated_manager_name: ManagerName, +): + input_spec_1, molecules_1, result_data_1 = load_test_data("rxn_H2O_psi4_mp2_optsp") + + meta_1, id_1 = storage_socket.records.reaction.add( + [molecules_1], input_spec_1, "test_tag", PriorityEnum.low, None, None, True + ) + id_1 = id_1[0] + assert meta_1.success + + run_service(storage_socket, activated_manager_name, id_1, generate_task_key, result_data_1, 1000) + + rec_1 = session.get(ReactionRecordORM, id_1) + assert rec_1.status == RecordStatusEnum.complete + opt_ids_1 = [x.optimization_id for x in rec_1.components] + sp_ids_1 = [x.singlepoint_id for x in rec_1.components] + + # Submit again, without duplicate checking + meta_2, id_2 = storage_socket.records.reaction.add( + [molecules_1], input_spec_1, "test_tag", PriorityEnum.low, None, None, False + ) + id_2 = id_2[0] + assert meta_2.success + assert id_2 != id_1 + + run_service(storage_socket, activated_manager_name, id_2, generate_task_key, result_data_1, 1000) + + rec_2 = session.get(ReactionRecordORM, id_2) + assert rec_2.status == RecordStatusEnum.complete + opt_ids_2 = [x.optimization_id for x in rec_2.components] + sp_ids_2 = [x.singlepoint_id for x in rec_2.components] + + assert set(opt_ids_1 + sp_ids_1).isdisjoint(opt_ids_2 + sp_ids_2) diff --git a/qcfractal/qcfractal/components/torsiondrive/test_record_socket.py b/qcfractal/qcfractal/components/torsiondrive/test_record_socket.py index 67ec98f0c..3d4388f52 100644 --- a/qcfractal/qcfractal/components/torsiondrive/test_record_socket.py +++ b/qcfractal/qcfractal/components/torsiondrive/test_record_socket.py @@ -293,11 +293,12 @@ def test_torsiondrive_socket_run( meta_1, id_1 = storage_socket.records.torsiondrive.add( [molecules_1], input_spec_1, True, "test_tag", PriorityEnum.low, "submit_user", "group1", True ) + id_1 = id_1[0] assert meta_1.success time_0 = datetime.utcnow() finished, n_optimizations = run_service( - storage_socket, activated_manager_name, id_1[0], generate_task_key, result_data_1, 1000 + storage_socket, activated_manager_name, id_1, generate_task_key, result_data_1, 1000 ) time_1 = datetime.utcnow() @@ -311,7 +312,7 @@ def test_torsiondrive_socket_run( assert time_0 < rec.compute_history[-1].modified_on < time_1 assert rec.service is None - desc_info = storage_socket.records.get_short_descriptions(id_1)[0] + desc_info = storage_socket.records.get_short_descriptions([id_1])[0] short_desc = desc_info["description"] assert desc_info["record_type"] == rec.record_type assert desc_info["created_on"] == rec.created_on @@ -324,3 +325,39 @@ def test_torsiondrive_socket_run( assert "Job Finished" in out assert len(rec.optimizations) == n_optimizations + + +def test_torsiondrive_socket_run_duplicate( + storage_socket: SQLAlchemySocket, + session: Session, + activated_manager_name: ManagerName, +): + input_spec_1, molecules_1, result_data_1 = load_test_data("td_H2O2_mopac_pm6") + + meta_1, id_1 = storage_socket.records.torsiondrive.add( + [molecules_1], input_spec_1, True, "test_tag", PriorityEnum.low, None, None, True + ) + id_1 = id_1[0] + assert meta_1.success + + run_service(storage_socket, activated_manager_name, id_1, generate_task_key, result_data_1, 1000) + + rec_1 = session.get(TorsiondriveRecordORM, id_1) + assert rec_1.status == RecordStatusEnum.complete + opt_ids_1 = [x.optimization_id for x in rec_1.optimizations] + + # Submit again, without duplicate checking + meta_2, id_2 = storage_socket.records.torsiondrive.add( + [molecules_1], input_spec_1, True, "test_tag", PriorityEnum.low, None, None, False + ) + id_2 = id_2[0] + assert meta_2.success + assert id_2 != id_1 + + run_service(storage_socket, activated_manager_name, id_2, generate_task_key, result_data_1, 1000) + + rec_2 = session.get(TorsiondriveRecordORM, id_2) + assert rec_2.status == RecordStatusEnum.complete + opt_ids_2 = [x.optimization_id for x in rec_2.optimizations] + + assert set(opt_ids_1).isdisjoint(opt_ids_2)