Files
rdkit/External/AvalonTools/test1.cpp
Ricardo Rodriguez 7b7a8a4e17 Refactor iostreams includes (#8846)
* refactor iostreams includes

* restore ostream to MonomerInfo.cpp
2025-10-08 16:08:01 +02:00

649 lines
20 KiB
C++

//
// Copyright (C) 2008-2021 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.
//
//
// Created by Greg Landrum, July 2008
//
//
// Expected test results here correspond to v1.0 of the open-source
// avalontoolkit
//
#include <RDGeneral/test.h>
#include <RDGeneral/RDLog.h>
#include <GraphMol/RDKitBase.h>
#include <GraphMol/SmilesParse/SmilesParse.h>
#include <GraphMol/SmilesParse/SmilesWrite.h>
#include <GraphMol/FileParsers/FileParsers.h>
#include <RDGeneral/Invariant.h>
#include <DataStructs/ExplicitBitVect.h>
#include <fstream>
#include <cstdio>
#include "AvalonTools.h"
#include <string>
using namespace RDKit;
void test1() {
BOOST_LOG(rdInfoLog) << "testing canonical smiles generation" << std::endl;
{
ROMol *m = static_cast<ROMol *>(SmilesToMol("c1ccccc1"));
TEST_ASSERT(m);
std::string smi = AvalonTools::getCanonSmiles(*m);
TEST_ASSERT(smi == "c1ccccc1");
delete m;
}
{
ROMol *m = static_cast<ROMol *>(SmilesToMol("c1cccnc1"));
TEST_ASSERT(m);
std::string smi = AvalonTools::getCanonSmiles(*m);
TEST_ASSERT(smi == "c1ccncc1");
delete m;
}
{
ROMol *m = static_cast<ROMol *>(SmilesToMol("n1ccccc1"));
TEST_ASSERT(m);
std::string smi = AvalonTools::getCanonSmiles(*m);
TEST_ASSERT(smi == "c1ccncc1");
delete m;
}
{
std::string smi = AvalonTools::getCanonSmiles("n1ccccc1", true);
TEST_ASSERT(smi == "c1ccncc1");
}
{
std::string smi = AvalonTools::getCanonSmiles("c1cccnc1", true);
TEST_ASSERT(smi == "c1ccncc1");
}
BOOST_LOG(rdInfoLog) << "done" << std::endl;
}
void test2() {
BOOST_LOG(rdInfoLog) << "testing coordinate generation" << std::endl;
#if 1
{
RWMol *m = SmilesToMol("c1cccnc1");
TEST_ASSERT(m);
unsigned int confId = AvalonTools::set2DCoords(*m);
TEST_ASSERT(m->getNumConformers() == 1);
TEST_ASSERT(confId == 0);
delete m;
}
#endif
{
std::string molb = AvalonTools::set2DCoords("c1cccnc1", true);
TEST_ASSERT(molb != "");
}
BOOST_LOG(rdInfoLog) << "done" << std::endl;
}
void test3() {
BOOST_LOG(rdInfoLog) << "testing fingerprint generation" << std::endl;
{
ROMol *m = static_cast<ROMol *>(SmilesToMol("c1ccccn1"));
TEST_ASSERT(m);
ExplicitBitVect bv(512);
AvalonTools::getAvalonFP(*m, bv, 512, false, true, 0x00006FFF);
BOOST_LOG(rdInfoLog) << "c1ccccn1 " << bv.getNumOnBits() << std::endl;
TEST_ASSERT(bv.getNumOnBits() == 18);
delete m;
}
{
ROMol *m = static_cast<ROMol *>(SmilesToMol("c1ccccc1"));
TEST_ASSERT(m);
ExplicitBitVect bv(512);
AvalonTools::getAvalonFP(*m, bv, 512, false, true, 0x006FFF);
BOOST_LOG(rdInfoLog) << "c1ccccn1 " << bv.getNumOnBits() << std::endl;
TEST_ASSERT(bv.getNumOnBits() == 6);
delete m;
}
{
ROMol *m = static_cast<ROMol *>(SmilesToMol("c1nnccc1"));
TEST_ASSERT(m);
ExplicitBitVect bv(512);
AvalonTools::getAvalonFP(*m, bv, 512, false, true, 0x006FFF);
BOOST_LOG(rdInfoLog) << "c1nnccc1 " << bv.getNumOnBits() << std::endl;
TEST_ASSERT(bv.getNumOnBits() == 28);
delete m;
}
{
ROMol *m = static_cast<ROMol *>(SmilesToMol("c1ncncc1"));
TEST_ASSERT(m);
ExplicitBitVect bv(512);
AvalonTools::getAvalonFP(*m, bv, 512, false, true, 0x006FFF);
BOOST_LOG(rdInfoLog) << "c1ncncc1 " << bv.getNumOnBits() << std::endl;
TEST_ASSERT(bv.getNumOnBits() == 25);
delete m;
}
{
ExplicitBitVect bv(512);
AvalonTools::getAvalonFP("c1cccnc1", true, bv, 512, false, true, 0x006FFF);
BOOST_LOG(rdInfoLog) << "c1cccnc1 " << bv.getNumOnBits() << std::endl;
TEST_ASSERT(bv.getNumOnBits() == 18);
}
{
ExplicitBitVect bv(512);
AvalonTools::getAvalonFP("c1ccccc1", true, bv, 512, false, true, 0x006FFF);
BOOST_LOG(rdInfoLog) << "c1ccccc1 " << bv.getNumOnBits() << std::endl;
TEST_ASSERT(bv.getNumOnBits() == 6);
}
{
ROMol *m = static_cast<ROMol *>(SmilesToMol("c1cccnc1"));
TEST_ASSERT(m);
ExplicitBitVect bv(1024);
AvalonTools::getAvalonFP(*m, bv, 1024, false, true, 0x006FFF);
BOOST_LOG(rdInfoLog) << "c1cccnc1 " << bv.getNumOnBits() << std::endl;
TEST_ASSERT(bv.getNumOnBits() == 19);
delete m;
}
{
ExplicitBitVect bv(2048);
AvalonTools::getAvalonFP("c1cocc1", true, bv, 2048, false, true, 0x006FFF);
BOOST_LOG(rdInfoLog) << "c1cocc1 " << bv.getNumOnBits() << std::endl;
TEST_ASSERT(bv.getNumOnBits() == 53);
}
{
ExplicitBitVect bv(2048);
AvalonTools::getAvalonFP("C1=COC=C1", true, bv, 2048, false, true,
0x006FFF);
BOOST_LOG(rdInfoLog) << "C1=COC=C1 " << bv.getNumOnBits() << std::endl;
TEST_ASSERT(bv.getNumOnBits() == 53);
}
BOOST_LOG(rdInfoLog) << "done" << std::endl;
}
void testGitHub1062() {
BOOST_LOG(rdInfoLog) << "testing GitHub issue #1062: pyAvalonTools not "
"preserving the stereochemistry of double bonds when "
"computing 2D coordinates"
<< std::endl;
{
std::string s0 = "C/C=C\\C";
ROMol *m1 = SmilesToMol(s0);
auto s1 = MolToSmiles(*m1);
AvalonTools::set2DCoords(*m1);
std::string mb = MolToMolBlock(*m1);
ROMol *m2 = MolBlockToMol(mb);
std::string s2 = MolToSmiles(*m2);
delete m1;
delete m2;
TEST_ASSERT(s1 == s2);
}
{
// repeat the test with an input smiles that is not canonical
// to verify that the implementation is not sensitive to the
// ordering of atoms
std::string s0 = "C/C=C(F)\\C";
ROMol *m1 = SmilesToMol(s0);
auto s1 = MolToSmiles(*m1);
TEST_ASSERT(s1 != s0);
AvalonTools::set2DCoords(*m1);
std::string mb = MolToMolBlock(*m1);
ROMol *m2 = MolBlockToMol(mb);
std::string s2 = MolToSmiles(*m2);
delete m1;
delete m2;
TEST_ASSERT(s1 == s2);
}
}
void testRDK151() {
BOOST_LOG(rdInfoLog) << "testing Jira issue RDK-151: pyAvalonTools not "
"generating chiral smiles from molecules"
<< std::endl;
{
std::string tSmi = "C[C@H](F)Cl";
auto *m = static_cast<ROMol *>(SmilesToMol(tSmi));
TEST_ASSERT(m);
std::string smi = AvalonTools::getCanonSmiles(tSmi, true);
CHECK_INVARIANT(smi == tSmi, smi + "!=" + tSmi);
smi = AvalonTools::getCanonSmiles(*m);
CHECK_INVARIANT(smi == tSmi, smi + "!=" + tSmi);
delete m;
}
BOOST_LOG(rdInfoLog) << "done" << std::endl;
}
void testSmilesFailures() {
BOOST_LOG(rdInfoLog) << "testing handling of bad smiles strings" << std::endl;
{
std::string tSmi = "C1C";
std::string smi = AvalonTools::getCanonSmiles(tSmi, true);
CHECK_INVARIANT(smi == "", smi);
}
BOOST_LOG(rdInfoLog) << "done" << std::endl;
}
void testSubstructFps() {
BOOST_LOG(rdInfoLog) << "testing substructure fingerprints " << std::endl;
{
ExplicitBitVect bv1(512), bv2(512);
AvalonTools::getAvalonFP("c1ccccc1", true, bv1, 512, true, true,
AvalonTools::avalonSSSBits);
AvalonTools::getAvalonFP("c1ccccc1C(F)(F)F", true, bv2, 512);
TEST_ASSERT((bv1 & bv2) == bv1);
AvalonTools::getAvalonFP("c1ccccc1C(F)(F)F", true, bv1, 512);
TEST_ASSERT((bv1 & bv2) == bv1);
AvalonTools::getAvalonFP("c1cccc(C)c1C(F)(F)F", true, bv2, 512);
TEST_ASSERT((bv1 & bv2) == bv1);
}
{
ExplicitBitVect bv1(512), bv2(512);
AvalonTools::getAvalonFP("c1ccccc1O", true, bv1, 512, true, true,
AvalonTools::avalonSSSBits);
AvalonTools::getAvalonFP("c1ccccc1OC", true, bv2, 512);
TEST_ASSERT((bv1 & bv2) == bv1);
}
BOOST_LOG(rdInfoLog) << "done" << std::endl;
}
void testStruChk() {
BOOST_LOG(rdInfoLog) << "testing structure checking " << std::endl;
{
int errs = 0;
RDKit::ROMOL_SPTR m = AvalonTools::checkMol(errs, "c1ccccc1", true);
TEST_ASSERT(errs == 0);
m = AvalonTools::checkMol(errs, "c1c(R)cccc1C1(CC-C(C)C1)C", true);
TEST_ASSERT(errs != 0);
}
{
int errs = 0;
std::string res;
boost::tie(res, errs) = AvalonTools::checkMolString("c1ccccc1", true);
TEST_ASSERT(errs == 0);
TEST_ASSERT(res != "");
boost::tie(res, errs) =
AvalonTools::checkMolString("c1c(R)cccc1C1(CC-C(C)C1)C", true);
TEST_ASSERT(errs == 1);
TEST_ASSERT(res == "");
}
BOOST_LOG(rdInfoLog) << "done" << std::endl;
}
void testBadMolfile() {
BOOST_LOG(rdInfoLog) << "testing handling bad molecules " << std::endl;
// some tests around dealing with bad mol blocks
{
std::string molb =
"SNAP007157A\n\
MACCS-II3194121345\n\
\n\
0 0 0 0 0";
std::string smi = AvalonTools::getCanonSmiles(molb, false);
CHECK_INVARIANT(smi == "", smi);
ExplicitBitVect bv(1024);
AvalonTools::getAvalonFP(molb, false, bv, 1024);
TEST_ASSERT(bv.getNumOnBits() == 0);
std::string oMolb;
AvalonTools::set2DCoords(molb, false);
CHECK_INVARIANT(oMolb == "", oMolb);
}
}
void testSmilesSegFault() {
BOOST_LOG(rdInfoLog)
<< "testing a canonical smiles case that led to seg faults " << std::endl;
// some tests around dealing with bad mol blocks
{
std::string inSmi(1024, 'C');
std::string smi = AvalonTools::getCanonSmiles(inSmi, true);
TEST_ASSERT(smi == inSmi);
}
{
std::string inSmi(1534, 'C');
std::string smi = AvalonTools::getCanonSmiles(inSmi, true);
TEST_ASSERT(smi == inSmi);
}
BOOST_LOG(rdInfoLog) << "done" << std::endl;
}
void testGithub336() {
BOOST_LOG(rdInfoLog) << "testing github issue 336: bad canonical smiles for "
"conjugated double bonds"
<< std::endl;
// some tests around dealing with bad mol blocks
{
std::string pathName = getenv("RDBASE");
pathName += "/External/AvalonTools/test_data/";
std::ifstream ins((pathName + "EZ_test.2.sdf").c_str());
std::string mb((std::istreambuf_iterator<char>(ins)),
std::istreambuf_iterator<char>());
ROMol *m = MolBlockToMol(mb);
TEST_ASSERT(m);
TEST_ASSERT(m->getNumAtoms() == 17);
std::string smi1 = AvalonTools::getCanonSmiles(mb, false);
std::string smi2 = AvalonTools::getCanonSmiles(*m);
std::cerr << "smi1: " << smi1 << std::endl;
std::cerr << "smi2: " << smi2 << std::endl;
TEST_ASSERT(smi1 == smi2);
delete m;
}
{
std::string pathName = getenv("RDBASE");
pathName += "/External/AvalonTools/test_data/";
std::ifstream ins((pathName + "heterocycle.mol").c_str());
std::string mb((std::istreambuf_iterator<char>(ins)),
std::istreambuf_iterator<char>());
RWMol *m = MolBlockToMol(mb, false);
TEST_ASSERT(m);
TEST_ASSERT(m->getNumAtoms() == 6);
m->updatePropertyCache();
MolOps::cleanUp(*m);
MolOps::setAromaticity(*m);
std::string smi1 = AvalonTools::getCanonSmiles(mb, false);
std::string smi2 = AvalonTools::getCanonSmiles(*m);
std::cerr << "smi1: " << smi1 << std::endl;
std::cerr << "smi2: " << smi2 << std::endl;
TEST_ASSERT(smi1 == smi2);
TEST_ASSERT(smi1 == "CC1C=NNC=1");
delete m;
}
{
std::string pathName = getenv("RDBASE");
pathName += "/External/AvalonTools/test_data/";
std::ifstream ins((pathName + "heterocycle2.mol").c_str());
std::string mb((std::istreambuf_iterator<char>(ins)),
std::istreambuf_iterator<char>());
RWMol *m = MolBlockToMol(mb, false);
TEST_ASSERT(m);
TEST_ASSERT(m->getNumAtoms() == 11);
m->updatePropertyCache();
MolOps::cleanUp(*m);
MolOps::setAromaticity(*m);
std::string smi1 = AvalonTools::getCanonSmiles(mb, false);
std::string smi2 = AvalonTools::getCanonSmiles(*m);
std::cerr << "smi1: " << smi1 << std::endl;
std::cerr << "smi2: " << smi2 << std::endl;
TEST_ASSERT(smi1 == smi2);
TEST_ASSERT(smi1 == "CN2C=CC1=CC(=O)NC=C12");
delete m;
}
BOOST_LOG(rdInfoLog) << "done" << std::endl;
}
void testCountFps() {
BOOST_LOG(rdInfoLog) << "testing substructure fingerprints " << std::endl;
{
SparseIntVect<boost::uint32_t> cv1(5000), cv2(5000);
AvalonTools::getAvalonCountFP("c1ccccc1", true, cv1, 5000);
AvalonTools::getAvalonCountFP("c1ccccc1.c1ccccc1", true, cv2, 5000);
for (unsigned int i = 0; i < cv1.size(); ++i) {
if (cv1[i] && (cv2[i] != 2 * cv1[i])) {
std::cerr << " mismatch: " << i << " " << cv1[i] << " " << cv2[i]
<< std::endl;
}
}
for (unsigned int i = 0; i < cv1.size(); ++i) {
TEST_ASSERT(!cv1[i] || (cv2[i] == 2 * cv1[i]));
}
}
{
ROMol *m1 = static_cast<ROMol *>(SmilesToMol("c1ccccc1"));
TEST_ASSERT(m1);
ROMol *m2 = static_cast<ROMol *>(SmilesToMol("c1ccccc1.c1ccccc1"));
TEST_ASSERT(m2);
SparseIntVect<boost::uint32_t> cv1(5000), cv2(5000);
AvalonTools::getAvalonCountFP(*m1, cv1, 5000);
AvalonTools::getAvalonCountFP(*m2, cv2, 5000);
for (unsigned int i = 0; i < cv1.size(); ++i) {
if (cv1[i] && (cv2[i] != 2 * cv1[i])) {
std::cerr << " mismatch: " << i << " " << cv1[i] << " " << cv2[i]
<< std::endl;
}
}
for (unsigned int i = 0; i < cv1.size(); ++i) {
TEST_ASSERT(!cv1[i] || (cv2[i] == 2 * cv1[i]));
}
delete m1;
delete m2;
}
BOOST_LOG(rdInfoLog) << "done" << std::endl;
}
void testInitStruChk() {
BOOST_LOG(rdInfoLog) << "testing init struchk " << std::endl;
{
std::string pathName = getenv("RDBASE");
pathName += "/Data/struchk/";
std::string struchk_init =
"-tm\n"
"-ta " +
pathName + std::string("checkfgs.trn\n") +
"-tm\n"
"-or\n"
"-ca " +
pathName + std::string("checkfgs.chk\n") +
"-cc\n"
"-cl 3\n"
"-cs\n"
"-cn 999\n"
"-l " +
#ifdef _WIN32
std::getenv("TEMP") +
#endif
std::string(std::tmpnam(nullptr)) + std::string("\n");
int errs = AvalonTools::initCheckMol(struchk_init);
TEST_ASSERT(!errs);
RDKit::ROMOL_SPTR m = AvalonTools::checkMol(errs, "c1ccccc1", true);
AvalonTools::closeCheckMolFiles();
TEST_ASSERT(errs == 0);
}
BOOST_LOG(rdInfoLog) << "done" << std::endl;
}
void testGithub4075() {
BOOST_LOG(rdInfoLog) << "testing Github #4075: AvalonTools.Generate2DCoords "
"results in an assert violation"
<< std::endl;
{
auto mol = "Cl[C@H](C)CCC(F)Cl"_smiles;
TEST_ASSERT(mol);
AvalonTools::set2DCoords(*mol);
TEST_ASSERT(mol->getNumConformers() == 1);
std::unique_ptr<ROMol> newMol(MolBlockToMol(MolToMolBlock(*mol)));
TEST_ASSERT(newMol);
TEST_ASSERT(MolToSmiles(*newMol) == MolToSmiles(*mol));
}
{
auto mol = "Cl[C@H](C)C([C@H](O)I)C[C@H](F)Cl"_smiles;
TEST_ASSERT(mol);
AvalonTools::set2DCoords(*mol);
TEST_ASSERT(mol->getNumConformers() == 1);
std::unique_ptr<ROMol> newMol(MolBlockToMol(MolToMolBlock(*mol)));
TEST_ASSERT(newMol);
TEST_ASSERT(MolToSmiles(*newMol) == MolToSmiles(*mol));
}
BOOST_LOG(rdInfoLog) << "done" << std::endl;
}
void testGithub4330() {
BOOST_LOG(rdInfoLog) << "testing Github #4330: AvalonTools::set2DCoords "
"failing for molecules which have Hs"
<< std::endl;
{
auto mol = "F[C@H](OOF)Br"_smiles;
TEST_ASSERT(mol);
AvalonTools::set2DCoords(*mol);
TEST_ASSERT(mol->getNumConformers() == 1);
MolOps::addHs(*mol);
AvalonTools::set2DCoords(*mol);
TEST_ASSERT(mol->getNumConformers() == 1);
}
{ // example with the explicit Hs already in the graph
SmilesParserParams params;
params.removeHs = false;
std::unique_ptr<RWMol> mol(SmilesToMol("F[C@]([H])(OOF)Br", params));
TEST_ASSERT(mol);
TEST_ASSERT(mol->getNumAtoms() == 7);
AvalonTools::set2DCoords(*mol);
TEST_ASSERT(mol->getNumConformers() == 1);
}
{
auto mol = "CC"_smiles;
TEST_ASSERT(mol);
AvalonTools::set2DCoords(*mol);
TEST_ASSERT(mol->getNumConformers() == 1);
MolOps::addHs(*mol);
AvalonTools::set2DCoords(*mol);
TEST_ASSERT(mol->getNumConformers() == 1);
}
BOOST_LOG(rdInfoLog) << "done" << std::endl;
}
void testNoAtomCTAB() {
BOOST_LOG(rdInfoLog) << "testing CTAB with no atoms" << std::endl;
std::string data =
"NullMol\r\n ChemDraw04291110502D\r\n\r\n 0 0 0 0 0 0 0 0 0 0999 V2000\r\nM END";
bool isSmiles = false;
int flags = 0x01 | 0x02 | 0x20;
auto res = AvalonTools::getCanonSmiles(data, isSmiles, flags);
TEST_ASSERT(res.empty());
}
void testBigMoleculeNoNewlineInInitString() {
BOOST_LOG(rdInfoLog) << "testing molecule with >150 atoms when "
"init string has no newline"
<< std::endl;
std::string pathName = getenv("RDBASE");
pathName += "/Data/struchk/";
std::stringstream struchk_init;
struchk_init << "-ta " << pathName << "checkfgs.trn\n"
<< "-tm\n"
"-or\n"
"-ca "
<< pathName << "checkfgs.chk\n"
<< "-cc\n"
"-cl 3\n"
"-cs\n"
"-cn 999";
int errs = AvalonTools::initCheckMol(struchk_init.str());
TEST_ASSERT(!errs);
std::string bigMol =
"CC(C)CC(C(=O)NC(CCSC)C(=O)NC(CC(=O)N)C(=O)NC(C(C)O)C(=O)O)NC(=O)C(CC1=CNC2=CC=CC=C21)NC(=O)C(CCC(=O)N)NC(=O)C(C(C)C)NC(=O)C(CC3=CC=CC=C3)NC(=O)C(CC(=O)O)NC(=O)C(CCC(=O)N)NC(=O)C(C)NC(=O)C(CCCNC(=N)N)NC(=O)C(CCCNC(=N)N)NC(=O)C(CO)NC(=O)C(CC(=O)O)NC(=O)C(CC(C)C)NC(=O)C(CC4=CC=C(C=C4)O)NC(=O)C(CCCCN)NC(=O)C(CO)NC(=O)C(CC5=CC=C(C=C5)O)NC(=O)C(CC(=O)O)NC(=O)C(CO)NC(=O)C(C(C)O)NC(=O)C(CC6=CC=CC=C6)NC(=O)C(C(C)O)NC(=O)CNC(=O)C(CCC(=O)N)NC(=O)C(CO)NC(=O)C(CC7=CN=CN7)N";
RDKit::ROMOL_SPTR m = AvalonTools::checkMol(errs, bigMol, true);
AvalonTools::closeCheckMolFiles();
TEST_ASSERT(errs == 0);
}
void testCrashOnCtabMisalignment() {
BOOST_LOG(rdInfoLog) << "testing crash on CTAB bond table misalignment"
<< std::endl;
std::string pathName = getenv("RDBASE");
pathName += "/Data/struchk/";
std::stringstream struchk_init;
struchk_init << "-ta " << pathName << "checkfgs.trn\n"
<< "-tm\n"
"-or\n"
"-ca "
<< pathName << "checkfgs.chk\n"
<< "-cc\n"
"-cl 3\n"
"-cs\n"
"-cn 999";
int errs = AvalonTools::initCheckMol(struchk_init.str());
TEST_ASSERT(!errs);
std::string ctab = R"CTAB(
RDKit 2D
3 2 0 0 0 0 0 0 0 0999 V2000
0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1.2990 0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.5981 -0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0
2 3 1 0
M END
)CTAB";
auto res = AvalonTools::checkMolString(ctab, false);
AvalonTools::closeCheckMolFiles();
TEST_ASSERT(!res.second);
TEST_ASSERT(res.first.find(" 1 2 1 0 0 0 0") != std::string::npos);
}
void testCrashOnBondAtomIdxOutOfBounds() {
BOOST_LOG(rdInfoLog)
<< "testing crash on CTAB bond table atom idx out of bounds" << std::endl;
std::string pathName = getenv("RDBASE");
pathName += "/Data/struchk/";
std::stringstream struchk_init;
struchk_init << "-ta " << pathName << "checkfgs.trn\n"
<< "-tm\n"
"-or\n"
"-ca "
<< pathName << "checkfgs.chk\n"
<< "-cc\n"
"-cl 3\n"
"-cs\n"
"-cn 999";
int errs = AvalonTools::initCheckMol(struchk_init.str());
TEST_ASSERT(!errs);
std::string ctab = R"CTAB(
RDKit 2D
3 2 0 0 0 0 0 0 0 0999 V2000
0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1.2990 0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.5981 -0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
10 20 1 0
2 3 1 0
M END
)CTAB";
auto res = AvalonTools::checkMolString(ctab, false);
AvalonTools::closeCheckMolFiles();
TEST_ASSERT(res.second);
}
int main() {
RDLog::InitLogs();
#if 1
test1();
test2();
test3();
testGitHub1062();
testRDK151();
testSmilesFailures();
testSubstructFps();
testStruChk();
testBadMolfile();
testSmilesSegFault();
testGithub336();
testCountFps();
testInitStruChk();
#endif
testGithub4075();
testGithub4330();
testNoAtomCTAB();
testBigMoleculeNoNewlineInInitString();
testCrashOnCtabMisalignment();
testCrashOnBondAtomIdxOutOfBounds();
return 0;
}