Files
rdkit/Code/GraphMol/GeneralizedSubstruct/catch_tests.cpp
Ric 2bd6481280 Fix some build warnings (#6618)
* fixes a copy constructor issue:

In copy constructor ‘boost::shared_ptr<T>::shared_ptr(const boost::shared_ptr<T>&) [with T = RDKit::ROMol]’,
    inlined from ‘PyObject* RDKit::RunReactant(ChemicalReaction*, T, unsigned int) [with T = boost::python::api::object]’ at /tmp/rdkit_builder/rdkit/Code/GraphMol/ChemReactions/Wrap/rdChemReactions.cpp:129:14:
/usr/include/boost/smart_ptr/shared_ptr.hpp:416:66: warning: ‘*(const boost::shared_ptr<RDKit::ROMol>*)((char*)&<unnamed> + offsetof(boost::python::extract<boost::shared_ptr<RDKit::ROMol> >,boost::python::extract<boost::shared_ptr<RDKit::ROMol> >::<unnamed>.boost::python::converter::extract_rvalue<boost::shared_ptr<RDKit::ROMol> >::m_data.boost::python::converter::rvalue_from_python_data<boost::shared_ptr<RDKit::ROMol> >::<unnamed>.boost::python::converter::rvalue_from_python_storage<boost::shared_ptr<RDKit::ROMol> >::storage)).boost::shared_ptr<RDKit::ROMol>::px’ may be used uninitialized [-Wmaybe-uninitialized]
  416 |     shared_ptr( shared_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
      |                                                                ~~^~
/tmp/rdkit_builder/rdkit/Code/GraphMol/ChemReactions/Wrap/rdChemReactions.cpp: In function ‘PyObject* RDKit::RunReactant(ChemicalReaction*, T, unsigned int) [with T = boost::python::api::object]’:
/tmp/rdkit_builder/rdkit/Code/GraphMol/ChemReactions/Wrap/rdChemReactions.cpp:129:30: note: ‘<anonymous>’ declared here
  129 |   ROMOL_SPTR react = python::extract<ROMOL_SPTR>(reactant);
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/smart_ptr/shared_ptr.hpp:17:
In copy constructor ‘boost::detail::shared_count::shared_count(const boost::detail::shared_count&)’,
    inlined from ‘boost::shared_ptr<T>::shared_ptr(const boost::shared_ptr<T>&) [with T = RDKit::ROMol]’ at /usr/include/boost/smart_ptr/shared_ptr.hpp:416:72,
    inlined from ‘PyObject* RDKit::RunReactant(ChemicalReaction*, T, unsigned int) [with T = boost::python::api::object]’ at /tmp/rdkit_builder/rdkit/Code/GraphMol/ChemReactions/Wrap/rdChemReactions.cpp:129:14:
/usr/include/boost/smart_ptr/detail/shared_count.hpp:438:67: warning: ‘((const boost::detail::shared_count*)((char*)&<unnamed> + offsetof(boost::python::extract<boost::shared_ptr<RDKit::ROMol> >,boost::python::extract<boost::shared_ptr<RDKit::ROMol> >::<unnamed>.boost::python::converter::extract_rvalue<boost::shared_ptr<RDKit::ROMol> >::m_data.boost::python::converter::rvalue_from_python_data<boost::shared_ptr<RDKit::ROMol> >::<unnamed>.boost::python::converter::rvalue_from_python_storage<boost::shared_ptr<RDKit::ROMol> >::storage)))[1].boost::detail::shared_count::pi_’ may be used uninitialized [-Wmaybe-uninitialized]
  438 |     shared_count(shared_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
      |                                                                 ~~^~~
/tmp/rdkit_builder/rdkit/Code/GraphMol/ChemReactions/Wrap/rdChemReactions.cpp: In function ‘PyObject* RDKit::RunReactant(ChemicalReaction*, T, unsigned int) [with T = boost::python::api::object]’:
/tmp/rdkit_builder/rdkit/Code/GraphMol/ChemReactions/Wrap/rdChemReactions.cpp:129:30: note: ‘<anonymous>’ declared here
  129 |   ROMOL_SPTR react = python::extract<ROMOL_SPTR>(reactant);
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* Fixes a (weird) allocation warning in GCC 12

In file included from /usr/include/c++/12/bits/alloc_traits.h:33,
                 from /usr/include/c++/12/ext/alloc_traits.h:34,
                 from /usr/include/c++/12/bits/basic_string.h:39,
                 from /usr/include/c++/12/string:53,
                 from /usr/include/c++/12/bits/locale_classes.h:40,
                 from /usr/include/c++/12/bits/ios_base.h:41,
                 from /usr/include/c++/12/streambuf:41,
                 from /usr/include/c++/12/bits/streambuf_iterator.h:35,
                 from /usr/include/c++/12/iterator:66,
                 from /usr/include/boost/iterator/iterator_traits.hpp:10,
                 from /usr/include/boost/range/iterator_range_core.hpp:26,
                 from /usr/include/boost/range/iterator_range.hpp:13,
                 from /usr/include/boost/iostreams/traits.hpp:38,
                 from /usr/include/boost/iostreams/detail/call_traits.hpp:15,
                 from /usr/include/boost/iostreams/detail/adapter/device_adapter.hpp:22,
                 from /usr/include/boost/iostreams/tee.hpp:18,
                 from /tmp/rdkit_builder/rdkit/Code/RDGeneral/RDLog.h:17,
                 from /tmp/rdkit_builder/rdkit/Code/GraphMol/ChemTransforms/testChemTransforms.cpp:11:
In function ‘void std::_Construct(_Tp*, _Args&& ...) [with _Tp = pair<int, int>; _Args = {const pair<int, int>&}]’,
    inlined from ‘_ForwardIterator std::__do_uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const pair<int, int>*; _ForwardIterator = pair<int, int>*]’ at /usr/include/c++/12/bits/stl_uninitialized.h:120:21,
    inlined from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const std::pair<int, int>*; _ForwardIterator = std::pair<int, int>*; bool _TrivialValueTypes = false]’ at /usr/include/c++/12/bits/stl_uninitialized.h:137:32,
    inlined from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const pair<int, int>*; _ForwardIterator = pair<int, int>*]’ at /usr/include/c++/12/bits/stl_uninitialized.h:185:15,
    inlined from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, allocator<_Tp>&) [with _InputIterator = const pair<int, int>*; _ForwardIterator = pair<int, int>*; _Tp = pair<int, int>]’ at /usr/include/c++/12/bits/stl_uninitialized.h:372:37,
    inlined from ‘void std::vector<_Tp, _Alloc>::_M_range_insert(iterator, _ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const std::pair<int, int>*; _Tp = std::pair<int, int>; _Alloc = std::allocator<std::pair<int, int> >]’ at /usr/include/c++/12/bits/vector.tcc:808:38,
    inlined from ‘std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::insert(const_iterator, std::initializer_list<_Tp>) [with _Tp = std::pair<int, int>; _Alloc = std::allocator<std::pair<int, int> >]’ at /usr/include/c++/12/bits/stl_vector.h:1409:17,
    inlined from ‘void testReplaceCoreMatchVectMultipleMappingToCore()’ at /tmp/rdkit_builder/rdkit/Code/GraphMol/ChemTransforms/testChemTransforms.cpp:974:17:
/usr/include/c++/12/bits/stl_construct.h:119:7: warning: ‘void* __builtin_memcpy(void*, const void*, long unsigned int)’ writing 56 bytes into a region of size 48 overflows the destination [-Wstringop-overflow=]
  119 |       ::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
      |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/x86_64-linux-gnu/c++/12/bits/c++allocator.h:33,
                 from /usr/include/c++/12/bits/allocator.h:46,
                 from /usr/include/c++/12/string:41:
In member function ‘_Tp* std::__new_allocator<_Tp>::allocate(size_type, const void*) [with _Tp = std::pair<int, int>]’,
    inlined from ‘static _Tp* std::allocator_traits<std::allocator<_CharT> >::allocate(allocator_type&, size_type) [with _Tp = std::pair<int, int>]’ at /usr/include/c++/12/bits/alloc_traits.h:464:28,
    inlined from ‘std::_Vector_base<_Tp, _Alloc>::pointer std::_Vector_base<_Tp, _Alloc>::_M_allocate(std::size_t) [with _Tp = std::pair<int, int>; _Alloc = std::allocator<std::pair<int, int> >]’ at /usr/include/c++/12/bits/stl_vector.h:378:33,
    inlined from ‘void std::vector<_Tp, _Alloc>::_M_range_insert(iterator, _ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const std::pair<int, int>*; _Tp = std::pair<int, int>; _Alloc = std::allocator<std::pair<int, int> >]’ at /usr/include/c++/12/bits/vector.tcc:799:40,
    inlined from ‘std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::insert(const_iterator, std::initializer_list<_Tp>) [with _Tp = std::pair<int, int>; _Alloc = std::allocator<std::pair<int, int> >]’ at /usr/include/c++/12/bits/stl_vector.h:1409:17,
    inlined from ‘void testReplaceCoreMatchVectMultipleMappingToCore()’ at /tmp/rdkit_builder/rdkit/Code/GraphMol/ChemTransforms/testChemTransforms.cpp:974:17:
/usr/include/c++/12/bits/new_allocator.h:137:55: note: at offset [8, 56] into destination object of size 56 allocated by ‘operator new’
  137 |         return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp)));
      |                                                       ^

* finalForce maybe uninitialized in inlined copy constructor

* failure is being used uninitialized

* MaeWriter::write overrides a method of the base class without being marked 'override'

This one is annoying because it happens in an exported header, so it propagates
to any code using the header!

* otq is never used

* fix implicitly declared assignment operator warning

* variables in catch statements that are never used

* fix type (sign) mismatch warning

* drop duplicate export macro
2023-08-11 06:04:55 +02:00

285 lines
12 KiB
C++

//
// Copyright (c) 2023, Greg Landrum and other RDKit contributors
//
// @@ All Rights Reserved @@
// This file is part of the RDKit.
// The contents are covered by the terms of the BSD license
// which is included in the file license.txt, found at the root
// of the RDKit source tree.
//
// Tests of the generalized substructure searching code
//
#include "catch.hpp"
#include <tuple>
#include <utility>
#include <GraphMol/RDKitBase.h>
#include <GraphMol/SmilesParse/SmilesParse.h>
#include <GraphMol/SmilesParse/SmilesWrite.h>
#include <GraphMol/SmilesParse/SmartsWrite.h>
#include <GraphMol/GeneralizedSubstruct/XQMol.h>
#include <GraphMol/TautomerQuery/TautomerQuery.h>
#include <GraphMol/MolEnumerator/MolEnumerator.h>
using namespace RDKit;
using namespace RDKit::GeneralizedSubstruct;
TEST_CASE("molecule basics") {
auto mol = "Cc1n[nH]c(F)c1"_smarts;
REQUIRE(mol);
ExtendedQueryMol xqm = std::make_unique<RWMol>(*mol);
SECTION("substructure matching and serialization") {
ExtendedQueryMol xqm2(xqm.toBinary());
ExtendedQueryMol xqm3(xqm.toJSON(), true);
for (const auto xq : {&xqm, &xqm2, &xqm3}) {
CHECK(SubstructMatch(*"CCc1n[nH]c(F)c1"_smiles, *xq).size() == 1);
CHECK(SubstructMatch(*"CCc1[nH]nc(F)c1"_smiles, *xq).empty());
CHECK(hasSubstructMatch(*"CCc1n[nH]c(F)c1"_smiles, *xq));
CHECK(!hasSubstructMatch(*"CCc1[nH]nc(F)c1"_smiles, *xq));
}
}
}
TEST_CASE("enumeration basics") {
auto mol = "COCC |LN:1:1.3|"_smiles;
REQUIRE(mol);
ExtendedQueryMol xqm =
std::make_unique<MolBundle>(MolEnumerator::enumerate(*mol));
SECTION("substructure matching and serialization") {
ExtendedQueryMol xqm2(xqm.toBinary());
ExtendedQueryMol xqm3(xqm.toJSON(), true);
for (const auto xq : {&xqm, &xqm2, &xqm3}) {
CHECK(SubstructMatch(*"COCC"_smiles, *xq).size() == 1);
CHECK(SubstructMatch(*"COOCC"_smiles, *xq).size() == 1);
CHECK(SubstructMatch(*"COOOCC"_smiles, *xq).size() == 1);
CHECK(SubstructMatch(*"COOOOCC"_smiles, *xq).empty());
}
}
}
TEST_CASE("result counts") {
auto mol = "COC |LN:1:1.3|"_smiles;
REQUIRE(mol);
ExtendedQueryMol xqm =
std::make_unique<MolBundle>(MolEnumerator::enumerate(*mol));
SECTION("substructure matching and serialization") {
ExtendedQueryMol xqm2(xqm.toBinary());
ExtendedQueryMol xqm3(xqm.toJSON(), true);
SubstructMatchParameters ps;
ps.uniquify = false;
for (const auto xq : {&xqm, &xqm2, &xqm3}) {
CHECK(SubstructMatch(*"COCC"_smiles, *xq, ps).size() == 2);
CHECK(SubstructMatch(*"COOCC"_smiles, *xq, ps).size() == 2);
CHECK(SubstructMatch(*"COOOCC"_smiles, *xq, ps).size() == 2);
CHECK(SubstructMatch(*"COOOOCC"_smiles, *xq, ps).empty());
}
}
}
TEST_CASE("tautomer basics") {
auto mol = "Cc1n[nH]c(F)c1"_smiles;
REQUIRE(mol);
ExtendedQueryMol xqm =
std::unique_ptr<TautomerQuery>(TautomerQuery::fromMol(*mol));
SECTION("substructure matching and serialization") {
ExtendedQueryMol xqm2(xqm.toBinary());
ExtendedQueryMol xqm3(xqm.toJSON(), true);
for (const auto xq : {&xqm, &xqm2, &xqm3}) {
CHECK(SubstructMatch(*"CCc1n[nH]c(F)c1"_smiles, *xq).size() == 1);
CHECK(SubstructMatch(*"CCc1[nH]nc(F)c1"_smiles, *xq).size() == 1);
CHECK(SubstructMatch(*"CCc1[nH]ncc1"_smiles, *xq).empty());
}
}
}
TEST_CASE("tautomer bundle basics") {
auto mol1 = "Cc1n[nH]c(F)c1"_smiles;
REQUIRE(mol1);
auto mol2 = "Cc1n[nH]cc1F"_smiles;
REQUIRE(mol2);
std::vector<std::unique_ptr<TautomerQuery>> tbndl;
tbndl.emplace_back(
std::unique_ptr<TautomerQuery>(TautomerQuery::fromMol(*mol1)));
tbndl.emplace_back(
std::unique_ptr<TautomerQuery>(TautomerQuery::fromMol(*mol2)));
ExtendedQueryMol xqm =
std::make_unique<std::vector<std::unique_ptr<TautomerQuery>>>(
std::move(tbndl));
SECTION("substructure matching and serialization") {
ExtendedQueryMol xqm2(xqm.toBinary());
ExtendedQueryMol xqm3(xqm.toJSON(), true);
for (const auto xq : {&xqm, &xqm2, &xqm3}) {
CHECK(SubstructMatch(*"CCc1n[nH]c(F)c1"_smiles, *xq).size() == 1);
CHECK(SubstructMatch(*"CCc1[nH]nc(F)c1"_smiles, *xq).size() == 1);
CHECK(SubstructMatch(*"CCc1[nH]ncc1F"_smiles, *xq).size() == 1);
CHECK(SubstructMatch(*"CCc1n[nH]cc1F"_smiles, *xq).size() == 1);
CHECK(SubstructMatch(*"CCc1[nH]ncc1"_smiles, *xq).empty());
}
}
}
TEST_CASE("createExtendedQueryMol") {
SECTION("RWMol") {
auto mol = "COCC"_smiles;
REQUIRE(mol);
auto xqm = createExtendedQueryMol(*mol);
CHECK(std::holds_alternative<ExtendedQueryMol::RWMol_T>(xqm.xqmol));
CHECK(SubstructMatch(*"COCC"_smiles, xqm).size() == 1);
CHECK(SubstructMatch(*"COOCC"_smiles, xqm).empty());
}
SECTION("MolBundle") {
auto mol = "COCC |LN:1:1.3|"_smiles;
REQUIRE(mol);
auto xqm = createExtendedQueryMol(*mol);
CHECK(std::holds_alternative<ExtendedQueryMol::MolBundle_T>(xqm.xqmol));
CHECK(SubstructMatch(*"COCC"_smiles, xqm).size() == 1);
CHECK(SubstructMatch(*"COOCC"_smiles, xqm).size() == 1);
CHECK(SubstructMatch(*"COOOCC"_smiles, xqm).size() == 1);
CHECK(SubstructMatch(*"COOOOCC"_smiles, xqm).empty());
}
SECTION("TautomerQuery") {
auto mol1 = "CC1OC(N)=N1"_smiles;
REQUIRE(mol1);
auto xqm = createExtendedQueryMol(*mol1);
CHECK(std::holds_alternative<ExtendedQueryMol::TautomerQuery_T>(xqm.xqmol));
CHECK(SubstructMatch(*"CCC1OC(N)=N1"_smiles, xqm).size() == 1);
CHECK(SubstructMatch(*"CCC1OC(=N)N1"_smiles, *mol1).empty());
CHECK(SubstructMatch(*"CCC1OC(=N)N1"_smiles, xqm).size() == 1);
CHECK(SubstructMatch(*"c1[nH]ncc1"_smiles, xqm).empty());
}
SECTION("TautomerBundle") {
auto mol1 = "COCC1OC(N)=N1 |LN:1:1.3|"_smiles;
REQUIRE(mol1);
auto xqm = createExtendedQueryMol(*mol1);
CHECK(
std::holds_alternative<ExtendedQueryMol::TautomerBundle_T>(xqm.xqmol));
CHECK(SubstructMatch(*"COCC1(F)OC(N)=N1"_smiles, xqm).size() == 1);
CHECK(SubstructMatch(*"COOCC1(F)OC(=N)N1"_smiles, xqm).size() == 1);
CHECK(SubstructMatch(*"COCC1OC(N)=N1"_smiles, xqm).size() == 1);
CHECK(SubstructMatch(*"COOOOCC1OC(=N)N1"_smiles, xqm).empty());
}
}
TEST_CASE("test SRUs") {
SECTION("basics") {
auto mol = "FCN(CC)-* |Sg:n:2,5:1-2:ht|"_smiles;
REQUIRE(mol);
auto xqm = createExtendedQueryMol(*mol);
CHECK(std::holds_alternative<ExtendedQueryMol::MolBundle_T>(xqm.xqmol));
// as of v2023.03.1 the SRU enumerator ignores repeat counts, so
// we won't test limits here.
CHECK(SubstructMatch(*"FCN(C)CC"_smiles, xqm).size() == 1);
CHECK(SubstructMatch(*"FCN(O)N(C)CC"_smiles, xqm).size() == 1);
}
}
// there's some redundancy in testing with what's above, but duplicating tests
// isn't a terrible thing
TEST_CASE("adjustQueryProperties") {
bool doEnumeration = true;
bool doTautomers = true;
bool adjustQueryProperties = true;
SECTION("RWMol") {
auto mol = "COC1CC1"_smiles;
REQUIRE(mol);
auto xqm1 = createExtendedQueryMol(*mol, doEnumeration, doTautomers);
auto xqm2 = createExtendedQueryMol(*mol, doEnumeration, doTautomers,
adjustQueryProperties);
MolOps::AdjustQueryParameters aqps =
MolOps::AdjustQueryParameters::noAdjustments();
aqps.makeAtomsGeneric = true;
auto xqm3 = createExtendedQueryMol(*mol, doEnumeration, doTautomers,
adjustQueryProperties, aqps);
CHECK(std::holds_alternative<ExtendedQueryMol::RWMol_T>(xqm1.xqmol));
CHECK(std::holds_alternative<ExtendedQueryMol::RWMol_T>(xqm2.xqmol));
CHECK(std::holds_alternative<ExtendedQueryMol::RWMol_T>(xqm3.xqmol));
CHECK(SubstructMatch(*"COC1CC1"_smiles, xqm1).size() == 1);
CHECK(SubstructMatch(*"COC1CC1"_smiles, xqm2).size() == 1);
CHECK(SubstructMatch(*"COC1CC1"_smiles, xqm3).size() == 1);
CHECK(SubstructMatch(*"COC1C(C)C1"_smiles, xqm1).size() == 1);
CHECK(SubstructMatch(*"COC1C(C)C1"_smiles, xqm2).empty());
CHECK(SubstructMatch(*"COC1C(C)C1"_smiles, xqm3).size() == 1);
CHECK(SubstructMatch(*"COC1OC1"_smiles, xqm1).empty());
CHECK(SubstructMatch(*"COC1OC1"_smiles, xqm2).empty());
CHECK(SubstructMatch(*"COC1OC1"_smiles, xqm3).size() == 1);
}
SECTION("MolBundle") {
auto mol = "COCC |LN:1:1.3|"_smiles;
REQUIRE(mol);
auto xqm1 = createExtendedQueryMol(*mol, doEnumeration, doTautomers);
MolOps::AdjustQueryParameters aqps =
MolOps::AdjustQueryParameters::noAdjustments();
aqps.makeBondsGeneric = true;
auto xqm2 = createExtendedQueryMol(*mol, doEnumeration, doTautomers,
adjustQueryProperties, aqps);
CHECK(std::holds_alternative<ExtendedQueryMol::MolBundle_T>(xqm1.xqmol));
CHECK(std::holds_alternative<ExtendedQueryMol::MolBundle_T>(xqm2.xqmol));
CHECK(SubstructMatch(*"COC=C"_smiles, xqm1).empty());
CHECK(SubstructMatch(*"COOC=C"_smiles, xqm1).empty());
CHECK(SubstructMatch(*"COC=C"_smiles, xqm2).size() == 1);
CHECK(SubstructMatch(*"COOC=C"_smiles, xqm2).size() == 1);
}
SECTION("TautomerQuery") {
auto mol1 = "CC1OC(N)=N1"_smiles;
REQUIRE(mol1);
auto xqm1 = createExtendedQueryMol(*mol1, doEnumeration, doTautomers);
auto xqm2 = createExtendedQueryMol(*mol1, doEnumeration, doTautomers,
adjustQueryProperties);
CHECK(
std::holds_alternative<ExtendedQueryMol::TautomerQuery_T>(xqm1.xqmol));
CHECK(
std::holds_alternative<ExtendedQueryMol::TautomerQuery_T>(xqm2.xqmol));
CHECK(SubstructMatch(*"CC1OC(N)=N1"_smiles, xqm1).size() == 1);
CHECK(SubstructMatch(*"CC1OC(N)=N1"_smiles, xqm2).size() == 1);
CHECK(SubstructMatch(*"CC1(F)OC(N)=N1"_smiles, xqm1).size() == 1);
CHECK(SubstructMatch(*"CC1(F)OC(=N)N1"_smiles, xqm1).size() == 1);
CHECK(SubstructMatch(*"CC1(F)OC(N)=N1"_smiles, xqm2).empty());
CHECK(SubstructMatch(*"CC1(F)OC(=N)N1"_smiles, xqm2).empty());
}
SECTION("TautomerBundle") {
auto mol1 = "COCC1OC(N)=N1 |LN:1:1.3|"_smiles;
REQUIRE(mol1);
auto xqm1 = createExtendedQueryMol(*mol1, doEnumeration, doTautomers);
auto xqm2 = createExtendedQueryMol(*mol1, doEnumeration, doTautomers,
adjustQueryProperties);
CHECK(
std::holds_alternative<ExtendedQueryMol::TautomerBundle_T>(xqm1.xqmol));
CHECK(SubstructMatch(*"COCC1OC(N)=N1"_smiles, xqm1).size() == 1);
CHECK(SubstructMatch(*"COOCC1OC(=N)N1"_smiles, xqm1).size() == 1);
CHECK(SubstructMatch(*"COCC1OC(N)=N1"_smiles, xqm2).size() == 1);
CHECK(SubstructMatch(*"COOCC1OC(=N)N1"_smiles, xqm2).size() == 1);
CHECK(SubstructMatch(*"COCC1(F)OC(N)=N1"_smiles, xqm1).size() == 1);
CHECK(SubstructMatch(*"COOCC1(F)OC(=N)N1"_smiles, xqm1).size() == 1);
CHECK(SubstructMatch(*"COCC1(F)OC(N)=N1"_smiles, xqm2).empty());
CHECK(SubstructMatch(*"COOCC1(F)OC(=N)N1"_smiles, xqm2).empty());
}
}
TEST_CASE("controlling which steps are applied") {
auto mol1 = "COCC1OC(N)=N1 |LN:1:1.3|"_smiles;
bool doEnumeration = true;
bool doTautomers = true;
REQUIRE(mol1);
{
auto xqm = createExtendedQueryMol(*mol1, doEnumeration, doTautomers);
CHECK(
std::holds_alternative<ExtendedQueryMol::TautomerBundle_T>(xqm.xqmol));
}
{
auto xqm = createExtendedQueryMol(*mol1, doEnumeration, false);
CHECK(std::holds_alternative<ExtendedQueryMol::MolBundle_T>(xqm.xqmol));
}
{
auto xqm = createExtendedQueryMol(*mol1, false, doTautomers);
CHECK(std::holds_alternative<ExtendedQueryMol::TautomerQuery_T>(xqm.xqmol));
}
{
auto xqm = createExtendedQueryMol(*mol1, false, false);
CHECK(std::holds_alternative<ExtendedQueryMol::RWMol_T>(xqm.xqmol));
}
}