// // Copyright (C) 2018 Greg Landrum // @@ 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. // #define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do // this in one cpp file #include "RDGeneral/test.h" #include "catch.hpp" #include #include #include #include #include using namespace RDKit; TEST_CASE("Basic SVG Parsing", "[SVG,parser]") { SECTION("basics") { std::string svg = R"SVG( NH Cl O OH m1 )SVG"; std::unique_ptr mol(RDKitSVGToMol(svg)); REQUIRE(mol); CHECK(mol->getNumAtoms() == 7); CHECK(mol->getNumConformers() == 1); CHECK_FALSE(mol->getConformer().is3D()); auto smiles = MolToSmiles(*mol); CHECK(smiles == "CN[C@H](Cl)C(=O)O"); } } TEST_CASE( "Github #2040: Failure to parse V3K mol file with bonds to multi-center " "linkage points", "[bug,parser]") { std::string rdbase = getenv("RDBASE"); SECTION("basics") { std::string fName = rdbase + "/Code/GraphMol/FileParsers/test_data/github2040_1.mol"; std::unique_ptr mol( MolFileToMol(fName, false)); // don't sanitize yet REQUIRE(mol); CHECK(mol->getBondWithIdx(0)->getBondType() == Bond::SINGLE); CHECK( mol->getBondWithIdx(0)->hasProp(common_properties::_MolFileBondEndPts)); CHECK(mol->getBondWithIdx(0)->getProp( common_properties::_MolFileBondEndPts) == "(3 5 4 3)"); CHECK( mol->getBondWithIdx(0)->hasProp(common_properties::_MolFileBondAttach)); CHECK(mol->getBondWithIdx(0)->getProp( common_properties::_MolFileBondAttach) == "ANY"); CHECK(mol->getBondWithIdx(1)->getBondType() == Bond::AROMATIC); } } TEST_CASE("Github #2225: failure round-tripping mol block with Q atoms", "[bug,writer]") { std::string rdbase = getenv("RDBASE"); SECTION("basics") { std::string fName = rdbase + "/Code/GraphMol/FileParsers/test_data/github2225_1.mol"; std::unique_ptr mol(MolFileToMol(fName)); REQUIRE(mol); REQUIRE(mol->getNumAtoms() == 7); REQUIRE(!mol->getAtomWithIdx(0)->hasQuery()); REQUIRE(mol->getAtomWithIdx(6)->hasQuery()); auto outBlock = MolToMolBlock(*mol); REQUIRE(outBlock.find(" Q ") != std::string::npos); REQUIRE(outBlock.find(" ALS ") == std::string::npos); std::unique_ptr mol2(MolBlockToMol(outBlock)); REQUIRE(mol2); REQUIRE(mol2->getNumAtoms() == 7); REQUIRE(!mol2->getAtomWithIdx(0)->hasQuery()); REQUIRE(mol2->getAtomWithIdx(6)->hasQuery()); auto outBlock2 = MolToMolBlock(*mol2); REQUIRE(outBlock2.find(" Q ") != std::string::npos); REQUIRE(outBlock2.find(" ALS ") == std::string::npos); } SECTION("check that SMARTS still works") { std::unique_ptr mol(SmartsToMol("C[#8,#7]")); REQUIRE(mol); REQUIRE(mol->getNumAtoms() == 2); auto outBlock = MolToMolBlock(*mol); REQUIRE(outBlock.find(" Q ") == std::string::npos); REQUIRE(outBlock.find(" ALS ") != std::string::npos); std::unique_ptr mol2(MolBlockToMol(outBlock)); REQUIRE(mol2); auto smarts = MolToSmarts(*mol2); REQUIRE(smarts == "[#6][#8,#7]"); } SECTION("basics with v3K") { std::string fName = rdbase + "/Code/GraphMol/FileParsers/test_data/github2225_2.mol"; std::unique_ptr mol(MolFileToMol(fName)); REQUIRE(mol); REQUIRE(mol->getNumAtoms() == 7); REQUIRE(!mol->getAtomWithIdx(0)->hasQuery()); REQUIRE(mol->getAtomWithIdx(6)->hasQuery()); bool includeStereo = true; int confId = -1; bool kekulize = true; bool forceV3000 = true; auto outBlock = MolToMolBlock(*mol, includeStereo, confId, kekulize, forceV3000); REQUIRE(outBlock.find(" Q ") != std::string::npos); REQUIRE(outBlock.find(" ALS ") == std::string::npos); std::unique_ptr mol2(MolBlockToMol(outBlock)); REQUIRE(mol2); REQUIRE(mol2->getNumAtoms() == 7); REQUIRE(!mol2->getAtomWithIdx(0)->hasQuery()); REQUIRE(mol2->getAtomWithIdx(6)->hasQuery()); auto outBlock2 = MolToMolBlock(*mol2, includeStereo, confId, kekulize, forceV3000); REQUIRE(outBlock2.find(" Q ") != std::string::npos); REQUIRE(outBlock2.find(" ALS ") == std::string::npos); } SECTION("check that SMARTS still works with v3K output") { std::unique_ptr mol(SmartsToMol("C[#8,#7]")); REQUIRE(mol); REQUIRE(mol->getNumAtoms() == 2); bool includeStereo = true; int confId = -1; bool kekulize = true; bool forceV3000 = true; auto outBlock = MolToMolBlock(*mol, includeStereo, confId, kekulize, forceV3000); REQUIRE(outBlock.find(" Q ") == std::string::npos); REQUIRE(outBlock.find(" [O,N] ") != std::string::npos); std::unique_ptr mol2(MolBlockToMol(outBlock)); REQUIRE(mol2); auto smarts = MolToSmarts(*mol2); REQUIRE(smarts == "[#6][#8,#7]"); } } TEST_CASE( "Github #2229: problem round-tripping mol files with bond topology info", "[bug,writer]") { std::string rdbase = getenv("RDBASE"); std::string fName = rdbase + "/Code/GraphMol/FileParsers/test_data/github2229_1.mol"; std::unique_ptr mol(MolFileToMol(fName)); REQUIRE(mol); REQUIRE(mol->getNumBonds() == 9); REQUIRE(!mol->getBondWithIdx(0)->hasQuery()); REQUIRE(mol->getBondWithIdx(7)->hasQuery()); SECTION("basics") { auto outBlock = MolToMolBlock(*mol); REQUIRE(outBlock.find(" 7 8 1 0 0 2") != std::string::npos); std::unique_ptr mol2(MolBlockToMol(outBlock)); REQUIRE(mol2); REQUIRE(mol2->getNumBonds() == 9); REQUIRE(!mol2->getBondWithIdx(0)->hasQuery()); REQUIRE(mol2->getBondWithIdx(7)->hasQuery()); } SECTION("basics with v3k") { bool includeStereo = true; int confId = -1; bool kekulize = true; bool forceV3000 = true; auto outBlock = MolToMolBlock(*mol, includeStereo, confId, kekulize, forceV3000); REQUIRE(outBlock.find("1 7 8 TOPO=2") != std::string::npos); std::unique_ptr mol2(MolBlockToMol(outBlock)); REQUIRE(mol2); REQUIRE(mol2->getNumBonds() == 9); REQUIRE(!mol2->getBondWithIdx(0)->hasQuery()); REQUIRE(mol2->getBondWithIdx(7)->hasQuery()); } }