1 //
2 // Copyright (C) 2001-2018 Greg Landrum and Rational Discovery LLC
3 //
4 // @@ All Rights Reserved @@
5 // This file is part of the RDKit.
6 // The contents are covered by the terms of the BSD license
7 // which is included in the file license.txt, found at the root
8 // of the RDKit source tree.
9 //
10
11 #include <RDGeneral/test.h>
12 #include <GraphMol/RDKitBase.h>
13 #include <GraphMol/MonomerInfo.h>
14 #include <GraphMol/RDKitQueries.h>
15 #include <RDGeneral/types.h>
16 #include <RDGeneral/RDLog.h>
17 //#include <boost/log/functions.hpp>
18 #include <GraphMol/FileParsers/FileParsers.h>
19 #include <GraphMol/FileParsers/MolWriters.h>
20 #include <GraphMol/SmilesParse/SmilesParse.h>
21 #include <GraphMol/SmilesParse/SmilesWrite.h>
22 #include <GraphMol/SmilesParse/SmartsWrite.h>
23 #include <sstream>
24 #include <iostream>
25 #include <boost/range/iterator_range.hpp>
26
27 using namespace std;
28 using namespace RDKit;
29
30 // -------------------------------------------------------------------
testBookmarks(ROMol m)31 void testBookmarks(ROMol m) {
32 int i;
33
34 // ------------------------
35 // simple bookmark stuff
36 Atom *a1 = m.getAtomWithIdx(1);
37 m.setAtomBookmark(a1, 666);
38 Atom *a2 = m.getAtomWithBookmark(666);
39
40 TEST_ASSERT(a2->getIdx() == a1->getIdx());
41
42 bool ok;
43 m.clearAtomBookmark(666);
44
45 boost::logging::disable_logs("rdApp.error");
46 try {
47 a2 = m.getAtomWithBookmark(666);
48 ok = 0;
49 } catch (...) {
50 ok = 1;
51 }
52 boost::logging::enable_logs("rdApp.error");
53 CHECK_INVARIANT(ok, "atom bookmark not properly cleared");
54
55 // ------------------------
56 // repeat a bookmark
57 a1 = m.getAtomWithIdx(1);
58 CHECK_INVARIANT(a1->getIdx() == 1, "");
59 m.setAtomBookmark(a1, 666);
60 m.setAtomBookmark(m.getAtomWithIdx(0), 666);
61 a2 = m.getAtomWithBookmark(666);
62 CHECK_INVARIANT(a2->getIdx() == 1, "");
63 CHECK_INVARIANT(a2->getIdx() == a1->getIdx(), "");
64 m.clearAtomBookmark(666, a2);
65 a2 = m.getAtomWithBookmark(666);
66 i = a2->getIdx();
67 CHECK_INVARIANT(i == 0, "");
68 m.clearAtomBookmark(666, a2);
69 boost::logging::disable_logs("rdApp.error");
70 try {
71 a2 = m.getAtomWithBookmark(666);
72 ok = 0;
73 } catch (...) {
74 ok = 1;
75 }
76 boost::logging::enable_logs("rdApp.error");
77 CHECK_INVARIANT(ok, "atom bookmark not properly cleared");
78
79 // make sure clearAtomBookmark doesn't barf if there's no
80 // such bookmark:
81 m.clearAtomBookmark(777);
82
83 //----------------------------
84 // now do bond bookmarks
85 Bond *b1 = m.getBondWithIdx(0);
86 m.setBondBookmark(b1, 23);
87 Bond *b2 = m.getBondWithBookmark(23);
88 CHECK_INVARIANT(b2->getIdx() == b1->getIdx(), "");
89
90 m.clearBondBookmark(23);
91 boost::logging::disable_logs("rdApp.error");
92 try {
93 b2 = m.getBondWithBookmark(23);
94 ok = 0;
95 } catch (...) {
96 ok = 1;
97 }
98 boost::logging::enable_logs("rdApp.error");
99 CHECK_INVARIANT(ok, "bond bookmark not properly cleared");
100
101 m.setBondBookmark(b1, 23);
102 m.setBondBookmark(m.getBondWithIdx(1), 23);
103 b2 = m.getBondWithBookmark(23);
104 CHECK_INVARIANT(b2->getIdx() == b1->getIdx(), "");
105 m.clearBondBookmark(23, b2);
106 b2 = m.getBondWithBookmark(23);
107 CHECK_INVARIANT(b2->getIdx() == 1, "");
108 m.clearBondBookmark(23, b2);
109 boost::logging::disable_logs("rdApp.error");
110 try {
111 b2 = m.getBondWithBookmark(23);
112 ok = 0;
113 } catch (...) {
114 ok = 1;
115 }
116 boost::logging::enable_logs("rdApp.error");
117 CHECK_INVARIANT(ok, "bond bookmark not properly cleared");
118
119 // make sure clearAtomBookmark doesn't barf if there's no
120 // such bookmark:
121 m.clearBondBookmark(777);
122 }
123
testMolProps()124 void testMolProps() {
125 BOOST_LOG(rdInfoLog)
126 << "-----------------------\n Testing Mol Property Caches" << std::endl;
127 RWMol m2;
128 STR_VECT propNames;
129
130 m2.addAtom(new Atom(6), true, true);
131 m2.addAtom(new Atom(6), true, true);
132 m2.addBond(0, 1, Bond::TRIPLE);
133
134 CHECK_INVARIANT(!m2.hasProp("prop1"), "");
135 CHECK_INVARIANT(!m2.hasProp("prop2"), "");
136 m2.setProp("prop1", 2);
137 int tmpI;
138 std::string tmpS;
139 CHECK_INVARIANT(m2.hasProp("prop1"), "");
140 m2.getProp("prop1", tmpI);
141 CHECK_INVARIANT(tmpI == 2, "");
142 m2.getProp("prop1", tmpS);
143 CHECK_INVARIANT(tmpS == "2", "");
144 m2.setProp("prop1", std::string("2"));
145 CHECK_INVARIANT(m2.hasProp("prop1"), "");
146 m2.getProp("prop1", tmpS);
147 CHECK_INVARIANT(tmpS == "2", "");
148 std::string tmpString("2");
149 m2.setProp("prop1", tmpString.c_str());
150 CHECK_INVARIANT(m2.hasProp("prop1"), "");
151 m2.getProp("prop1", tmpS);
152 CHECK_INVARIANT(tmpS == "2", "");
153
154 tmpS = "name";
155 m2.setProp(common_properties::_Name, tmpS);
156
157 propNames = m2.getPropList(false, false);
158 TEST_ASSERT(propNames.size() == 1);
159 propNames = m2.getPropList(true, false);
160 TEST_ASSERT(propNames.size() == 2);
161
162 // check for computed properties
163 m2.setProp("cprop1", 1, true);
164 m2.setProp("cprop2", 2, true);
165 STR_VECT cplst;
166 m2.getProp(RDKit::detail::computedPropName, cplst);
167 CHECK_INVARIANT(cplst.size() == 2, "");
168 CHECK_INVARIANT(cplst[0] == "cprop1", "");
169 CHECK_INVARIANT(cplst[1] == "cprop2", "");
170
171 propNames = m2.getPropList(false, false);
172 TEST_ASSERT(propNames.size() == 1);
173 propNames = m2.getPropList(true, false);
174 TEST_ASSERT(propNames.size() == 2);
175 propNames = m2.getPropList(false, true);
176 TEST_ASSERT(propNames.size() == 3);
177 propNames = m2.getPropList(true, true);
178 TEST_ASSERT(propNames.size() == 5);
179 propNames = m2.getPropList();
180 TEST_ASSERT(propNames.size() == 5);
181
182 m2.clearProp("cprop1");
183 CHECK_INVARIANT(!m2.hasProp("cprop1"), "");
184 m2.getProp(RDKit::detail::computedPropName, cplst);
185 CHECK_INVARIANT(cplst.size() == 1, "");
186
187 m2.clearComputedProps();
188 CHECK_INVARIANT(!m2.hasProp("cprop2"), "");
189 m2.getProp(RDKit::detail::computedPropName, cplst);
190 CHECK_INVARIANT(cplst.size() == 0, "");
191
192 BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
193 }
194
testClearMol()195 void testClearMol() {
196 BOOST_LOG(rdInfoLog) << "-----------------------\n Testing RWMol.clear()"
197 << std::endl;
198 RWMol m2;
199
200 m2.addAtom(new Atom(6), true, true);
201 m2.addAtom(new Atom(6), true, true);
202 m2.addBond(0, 1, Bond::TRIPLE);
203
204 TEST_ASSERT(!m2.hasProp("prop1"));
205 m2.setProp("prop1", 2);
206 int tmpI;
207 TEST_ASSERT(m2.hasProp("prop1"));
208 m2.getProp("prop1", tmpI);
209 TEST_ASSERT(tmpI == 2);
210
211 TEST_ASSERT(m2.hasProp(RDKit::detail::computedPropName));
212
213 m2.clear();
214 TEST_ASSERT(!m2.hasProp("prop1"));
215 TEST_ASSERT(m2.getNumAtoms() == 0);
216 TEST_ASSERT(m2.getNumBonds() == 0);
217 TEST_ASSERT(m2.getAtomBookmarks()->empty());
218 TEST_ASSERT(m2.getBondBookmarks()->empty());
219
220 TEST_ASSERT(
221 m2.hasProp(RDKit::detail::computedPropName)); // <- github issue 176
222 TEST_ASSERT(m2.getPropList().size() == 1);
223
224 BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
225 }
226
testAtomProps()227 void testAtomProps() {
228 BOOST_LOG(rdInfoLog)
229 << "-----------------------\n Testing Atom Property Caches" << std::endl;
230 RWMol m2;
231 m2.addAtom(new Atom(6), true, true);
232 m2.addAtom(new Atom(6), true, true);
233 m2.addBond(0, 1, Bond::TRIPLE);
234
235 Atom *a1 = m2.getAtomWithIdx(0);
236 Atom *a2 = m2.getAtomWithIdx(0);
237 Atom *a3 = &(*a1);
238 CHECK_INVARIANT(!a1->hasProp("prop1"), "");
239 CHECK_INVARIANT(!a1->hasProp("prop2"), "");
240 CHECK_INVARIANT(!a2->hasProp("prop1"), "");
241 CHECK_INVARIANT(!a2->hasProp("prop2"), "");
242 CHECK_INVARIANT(!a3->hasProp("prop1"), "");
243 CHECK_INVARIANT(!a3->hasProp("prop2"), "");
244 a1->setProp("prop1", 3);
245 a1->setProp("prop2", 4);
246 CHECK_INVARIANT(a1->hasProp("prop1"), "");
247 CHECK_INVARIANT(a1->hasProp("prop2"), "");
248 CHECK_INVARIANT(a2->hasProp("prop1"), "");
249 CHECK_INVARIANT(a2->hasProp("prop2"), "");
250 CHECK_INVARIANT(a3->hasProp("prop1"), "");
251 CHECK_INVARIANT(a3->hasProp("prop2"), "");
252 CHECK_INVARIANT(!a1->hasProp("bogus"), "");
253 CHECK_INVARIANT(!a2->hasProp("bogus"), "");
254 CHECK_INVARIANT(!a3->hasProp("bogus"), "");
255
256 bool ok = false;
257 a1->setProp<double>("dprop", 4);
258 TEST_ASSERT(a1->hasProp("dprop"));
259 try {
260 a1->getProp<int>("dprop");
261 } catch (const boost::bad_any_cast &) {
262 ok = true;
263 }
264 TEST_ASSERT(ok);
265 a1->setProp<int>("iprop", 4);
266 TEST_ASSERT(a1->hasProp("iprop"));
267 ok = false;
268 try {
269 a1->getProp<double>("iprop");
270 } catch (const boost::bad_any_cast &) {
271 ok = true;
272 }
273 TEST_ASSERT(ok);
274
275 int tmp;
276 a1->getProp("prop1", tmp);
277 CHECK_INVARIANT(tmp == 3, "");
278 a1->getProp("prop2", tmp);
279 CHECK_INVARIANT(tmp == 4, "");
280 a2->getProp("prop1", tmp);
281 CHECK_INVARIANT(tmp == 3, "");
282 a2->getProp("prop2", tmp);
283 CHECK_INVARIANT(tmp == 4, "");
284 a3->getProp("prop1", tmp);
285 CHECK_INVARIANT(tmp == 3, "");
286 a3->getProp("prop2", tmp);
287 CHECK_INVARIANT(tmp == 4, "");
288
289 // check for computed properties
290 a1->setProp("cprop1", 1, true);
291 a1->setProp("cprop2", 2, true);
292 STR_VECT cplst;
293 a1->getProp(RDKit::detail::computedPropName, cplst);
294 CHECK_INVARIANT(cplst.size() == 2, "");
295 CHECK_INVARIANT(cplst[0] == "cprop1", "");
296 CHECK_INVARIANT(cplst[1] == "cprop2", "");
297
298 a1->clearProp("cprop1");
299 CHECK_INVARIANT(!a1->hasProp("cprop1"), "");
300 a1->getProp(RDKit::detail::computedPropName, cplst);
301 CHECK_INVARIANT(cplst.size() == 1, "");
302
303 a1->clearComputedProps();
304 CHECK_INVARIANT(!a1->hasProp("cprop2"), "");
305 a1->getProp(RDKit::detail::computedPropName, cplst);
306 CHECK_INVARIANT(cplst.size() == 0, "");
307
308 BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
309 }
310
testBondProps()311 void testBondProps() {
312 BOOST_LOG(rdInfoLog)
313 << "-----------------------\n Testing Bond Property Caches" << std::endl;
314 RWMol m2;
315 m2.addAtom(new Atom(6), true, true);
316 m2.addAtom(new Atom(6), true, true);
317 m2.addBond(0, 1, Bond::TRIPLE);
318
319 Bond *b1 = m2.getBondWithIdx(0);
320 Bond *b2 = m2.getBondWithIdx(0);
321 CHECK_INVARIANT(!b1->hasProp("prop1"), "");
322 CHECK_INVARIANT(!b1->hasProp("prop2"), "");
323 CHECK_INVARIANT(!b2->hasProp("prop1"), "");
324 CHECK_INVARIANT(!b2->hasProp("prop2"), "");
325 b1->setProp("prop1", 3);
326 b1->setProp("prop2", 4);
327 CHECK_INVARIANT(b1->hasProp("prop1"), "");
328 CHECK_INVARIANT(b1->hasProp("prop2"), "");
329 CHECK_INVARIANT(b2->hasProp("prop1"), "");
330 CHECK_INVARIANT(b2->hasProp("prop2"), "");
331 CHECK_INVARIANT(!b1->hasProp("bogus"), "");
332 CHECK_INVARIANT(!b2->hasProp("bogus"), "");
333
334 int tmp;
335 b1->getProp("prop1", tmp);
336 CHECK_INVARIANT(tmp == 3, "");
337 b1->getProp("prop2", tmp);
338 CHECK_INVARIANT(tmp == 4, "");
339 b2->getProp("prop1", tmp);
340 CHECK_INVARIANT(tmp == 3, "");
341 b2->getProp("prop2", tmp);
342 CHECK_INVARIANT(tmp == 4, "");
343
344 // check for computed properties
345 b1->setProp("cprop1", 1, true);
346 b1->setProp("cprop2", 2, true);
347 STR_VECT cplst;
348 b1->getProp(RDKit::detail::computedPropName, cplst);
349 CHECK_INVARIANT(cplst.size() == 2, "");
350 CHECK_INVARIANT(cplst[0] == "cprop1", "");
351 CHECK_INVARIANT(cplst[1] == "cprop2", "");
352
353 b1->clearProp("cprop1");
354 CHECK_INVARIANT(!b1->hasProp("cprop1"), "");
355 b1->getProp(RDKit::detail::computedPropName, cplst);
356 CHECK_INVARIANT(cplst.size() == 1, "");
357
358 b1->clearComputedProps();
359 CHECK_INVARIANT(!b1->hasProp("cprop2"), "");
360 b1->getProp(RDKit::detail::computedPropName, cplst);
361 CHECK_INVARIANT(cplst.size() == 0, "");
362
363 BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
364 }
365
366 // this is here because there was at one time a problem with crashes when doing
367 // this stuff
testPropLeak()368 void testPropLeak() {
369 BOOST_LOG(rdInfoLog)
370 << "-----------------------\n Testing Atom and Bond Property Caches"
371 << std::endl;
372 RWMol m2;
373 m2.addAtom(new Atom(6), true, true);
374 m2.addAtom(new Atom(6), true, true);
375 m2.addBond(0, 1, Bond::TRIPLE);
376
377 Atom *a1 = m2.getAtomWithIdx(0);
378 Atom *a2 = m2.getAtomWithIdx(0);
379 CHECK_INVARIANT(!a1->hasProp("prop1"), "");
380 CHECK_INVARIANT(!a1->hasProp("prop2"), "");
381 CHECK_INVARIANT(!a2->hasProp("prop1"), "");
382 CHECK_INVARIANT(!a2->hasProp("prop2"), "");
383 a1->setProp("prop1", 3);
384 a1->setProp("prop2", 4);
385 CHECK_INVARIANT(a1->hasProp("prop1"), "");
386 CHECK_INVARIANT(a1->hasProp("prop2"), "");
387 CHECK_INVARIANT(a2->hasProp("prop1"), "");
388 CHECK_INVARIANT(a2->hasProp("prop2"), "");
389 CHECK_INVARIANT(!a1->hasProp("bogus"), "");
390 CHECK_INVARIANT(!a2->hasProp("bogus"), "");
391
392 int tmp;
393 a1->getProp("prop1", tmp);
394 CHECK_INVARIANT(tmp == 3, "");
395 a1->getProp("prop2", tmp);
396 CHECK_INVARIANT(tmp == 4, "");
397 a2->getProp("prop1", tmp);
398 CHECK_INVARIANT(tmp == 3, "");
399 a2->getProp("prop2", tmp);
400 CHECK_INVARIANT(tmp == 4, "");
401
402 Bond *b1 = m2.getBondWithIdx(0);
403 Bond *b2 = m2.getBondWithIdx(0);
404 CHECK_INVARIANT(!b1->hasProp("prop1"), "");
405 CHECK_INVARIANT(!b1->hasProp("prop2"), "");
406 CHECK_INVARIANT(!b2->hasProp("prop1"), "");
407 CHECK_INVARIANT(!b2->hasProp("prop2"), "");
408 b1->setProp("prop1", 3);
409 b1->setProp("prop2", 4);
410 CHECK_INVARIANT(b1->hasProp("prop1"), "");
411 CHECK_INVARIANT(b1->hasProp("prop2"), "");
412 CHECK_INVARIANT(b2->hasProp("prop1"), "");
413 CHECK_INVARIANT(b2->hasProp("prop2"), "");
414 CHECK_INVARIANT(!b1->hasProp("bogus"), "");
415 CHECK_INVARIANT(!b2->hasProp("bogus"), "");
416
417 b1->getProp("prop1", tmp);
418 CHECK_INVARIANT(tmp == 3, "");
419 b1->getProp("prop2", tmp);
420 CHECK_INVARIANT(tmp == 4, "");
421 b2->getProp("prop1", tmp);
422 CHECK_INVARIANT(tmp == 3, "");
423 b2->getProp("prop2", tmp);
424 CHECK_INVARIANT(tmp == 4, "");
425
426 BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
427 }
428
testMisc()429 void testMisc() {
430 BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Misc Properties"
431 << std::endl;
432 RWMol m2;
433 m2.addAtom(new Atom(6), true, true);
434 m2.addAtom(new Atom(6), true, true);
435 m2.addAtom(new Atom(6), true, true);
436 m2.addAtom(new Atom(6), true, true);
437 m2.addBond(0, 1, Bond::SINGLE);
438 m2.addBond(1, 2, Bond::SINGLE);
439 m2.addBond(0, 2, Bond::SINGLE);
440 m2.addBond(2, 3, Bond::SINGLE);
441
442 MolOps::sanitizeMol(m2);
443
444 Bond *bnd;
445 bnd = m2.getBondBetweenAtoms(0, 1);
446 CHECK_INVARIANT(bnd, "");
447 bnd = m2.getBondBetweenAtoms(1, 0);
448 CHECK_INVARIANT(bnd, "");
449 bnd = m2.getBondBetweenAtoms(3, 0);
450 CHECK_INVARIANT(!bnd, "");
451 bnd = m2.getBondBetweenAtoms(0, 3);
452 CHECK_INVARIANT(!bnd, "");
453 const Bond *cbnd;
454 cbnd = m2.getBondBetweenAtoms(0, 1);
455 CHECK_INVARIANT(cbnd, "");
456 cbnd = m2.getBondBetweenAtoms(1, 0);
457 CHECK_INVARIANT(cbnd, "");
458 cbnd = m2.getBondBetweenAtoms(0, 3);
459 CHECK_INVARIANT(!cbnd, "");
460 cbnd = m2.getBondBetweenAtoms(3, 0);
461 CHECK_INVARIANT(!cbnd, "");
462
463 CHECK_INVARIANT(m2.getAtomWithIdx(0)->getTotalNumHs() == 2, "");
464
465 // we'll check atom deletion and handling of bookmarks on deletion
466 // simultaneously:
467 // (The bookmark thing was the root of Issue 96)
468 m2.setAtomBookmark(m2.getAtomWithIdx(0), 2342);
469 m2.setBondBookmark(m2.getBondWithIdx(0), 2343);
470 m2.removeAtom(static_cast<unsigned int>(0));
471 CHECK_INVARIANT(!m2.hasAtomBookmark(2342), "");
472 CHECK_INVARIANT(!m2.hasBondBookmark(2343), "");
473 CHECK_INVARIANT(m2.getNumAtoms() == 3, "");
474 CHECK_INVARIANT(m2.getNumBonds() == 2, "");
475 MolOps::sanitizeMol(m2);
476 CHECK_INVARIANT(m2.getAtomWithIdx(0)->getTotalNumHs() == 3, "");
477
478 m2.addAtom(new Atom(1), true, true);
479 m2.addBond(2, 3, Bond::SINGLE);
480 MolOps::sanitizeMol(m2);
481
482 CHECK_INVARIANT(m2.getAtomWithIdx(0)->getTotalNumHs() == 3, "");
483 CHECK_INVARIANT(m2.getAtomWithIdx(0)->getTotalNumHs(true) == 3, "");
484 CHECK_INVARIANT(m2.getAtomWithIdx(2)->getTotalNumHs() == 2, "");
485 CHECK_INVARIANT(m2.getAtomWithIdx(2)->getTotalNumHs(true) == 3, "");
486
487 Atom *other = m2.getBondWithIdx(1)->getOtherAtom(m2.getAtomWithIdx(1));
488 CHECK_INVARIANT(other, "");
489
490 const Atom *at = m2.getAtomWithIdx(1);
491 ROMol::OEDGE_ITER begin, end;
492 boost::tie(begin, end) = m2.getAtomBonds(at);
493 while (begin != end) {
494 const Atom *at2 = m2[*begin]->getOtherAtom(at);
495 TEST_ASSERT(at2);
496 begin++;
497 }
498
499 ROMol::VERTEX_ITER atBegin, atEnd;
500 boost::tie(atBegin, atEnd) = m2.getVertices();
501 TEST_ASSERT(atBegin != atEnd);
502 while (atBegin != atEnd) {
503 const Atom *at2 = m2[*atBegin];
504 TEST_ASSERT(at2->getIdx() == *atBegin);
505 atBegin++;
506 }
507
508 BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
509 }
510
testDegree()511 void testDegree() {
512 BOOST_LOG(rdInfoLog) << "-----------------------\n Testing degree operations"
513 << std::endl;
514 RWMol *m;
515
516 m = new RWMol();
517 m->addAtom(new Atom(6), true, true);
518 m->addAtom(new Atom(6), true, true);
519 m->addAtom(new Atom(6), true, true);
520 m->addAtom(new Atom(6), true, true);
521 m->addBond(0, 1, Bond::SINGLE);
522 m->addBond(1, 2, Bond::SINGLE);
523 m->addBond(0, 2, Bond::SINGLE);
524 m->addBond(2, 3, Bond::SINGLE);
525
526 MolOps::sanitizeMol(*m);
527 TEST_ASSERT(m->getAtomWithIdx(0)->getDegree() == 2);
528 TEST_ASSERT(m->getAtomWithIdx(0)->getTotalNumHs() == 2);
529 TEST_ASSERT(m->getAtomWithIdx(0)->getTotalDegree() == 4);
530 TEST_ASSERT(m->getAtomWithIdx(2)->getDegree() == 3);
531 TEST_ASSERT(m->getAtomWithIdx(2)->getTotalNumHs() == 1);
532 TEST_ASSERT(m->getAtomWithIdx(2)->getTotalDegree() == 4);
533
534 delete m;
535 m = new RWMol();
536 m->addAtom(new Atom(6), true, true);
537 m->addAtom(new Atom(6), true, true);
538 m->addAtom(new Atom(6), true, true);
539 m->addAtom(new Atom(6), true, true);
540 m->addAtom(new Atom(1), true, true);
541 m->addBond(0, 1, Bond::SINGLE);
542 m->addBond(1, 2, Bond::SINGLE);
543 m->addBond(0, 2, Bond::SINGLE);
544 m->addBond(2, 3, Bond::SINGLE);
545 m->addBond(0, 4, Bond::SINGLE);
546
547 MolOps::sanitizeMol(*m);
548 TEST_ASSERT(m->getAtomWithIdx(0)->getDegree() == 3);
549 TEST_ASSERT(m->getAtomWithIdx(0)->getTotalNumHs() == 1);
550 TEST_ASSERT(m->getAtomWithIdx(0)->getTotalNumHs(true) == 2);
551 TEST_ASSERT(m->getAtomWithIdx(0)->getTotalDegree() == 4);
552 TEST_ASSERT(m->getAtomWithIdx(2)->getDegree() == 3);
553 TEST_ASSERT(m->getAtomWithIdx(2)->getTotalNumHs() == 1);
554 TEST_ASSERT(m->getAtomWithIdx(2)->getTotalDegree() == 4);
555 delete m;
556
557 BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
558 }
559
testIssue1993296()560 void testIssue1993296() {
561 auto *m = new RWMol();
562 bool ok;
563 BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl;
564 BOOST_LOG(rdInfoLog) << "Testing Issue 1993296" << std::endl;
565
566 m->addAtom(new Atom(6), true, true);
567 m->addAtom(new Atom(6), true, true);
568 m->addBond(0, 1, Bond::SINGLE);
569 ok = false;
570 try {
571 m->addBond(0, 1, Bond::SINGLE);
572 } catch (...) {
573 ok = true;
574 }
575 TEST_ASSERT(ok);
576 ok = false;
577 try {
578 m->addBond(1, 0, Bond::SINGLE);
579 } catch (...) {
580 ok = true;
581 }
582 TEST_ASSERT(ok);
583
584 // not technically part of 1993296, but related: we also throw
585 // on adding self bonds
586 ok = false;
587 try {
588 m->addBond(1, 1, Bond::SINGLE);
589 } catch (...) {
590 ok = true;
591 }
592
593 auto *newB = new Bond();
594 newB->setBeginAtomIdx(0);
595 newB->setEndAtomIdx(1);
596 newB->setBondType(Bond::SINGLE);
597 ok = false;
598 try {
599 m->addBond(newB);
600 } catch (...) {
601 ok = true;
602 }
603 TEST_ASSERT(ok);
604
605 // not technically part of 1993296, but related: we also throw
606 // on adding self bonds
607 newB->setBeginAtomIdx(0);
608 newB->setEndAtomIdx(0);
609 ok = false;
610 try {
611 m->addBond(newB);
612 } catch (...) {
613 ok = true;
614 }
615 TEST_ASSERT(ok);
616 delete newB;
617 delete m;
618
619 BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
620 }
621
testIssue2381580()622 void testIssue2381580() {
623 BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl;
624 BOOST_LOG(rdInfoLog) << "Testing Issue 2381580" << std::endl;
625
626 {
627 auto *m = new RWMol();
628 m->addAtom(new Atom(5), true, true);
629 m->addAtom(new Atom(6), true, true);
630 m->addAtom(new Atom(6), true, true);
631 m->addAtom(new Atom(6), true, true);
632 m->addBond(0, 1, Bond::SINGLE);
633 m->addBond(0, 2, Bond::SINGLE);
634 m->addBond(0, 3, Bond::SINGLE);
635 MolOps::sanitizeMol(*m);
636 TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 0);
637 TEST_ASSERT(m->getAtomWithIdx(0)->getExplicitValence() == 3);
638 TEST_ASSERT(m->getAtomWithIdx(0)->getNumImplicitHs() == 0);
639 delete m;
640 }
641
642 {
643 auto *m = new RWMol();
644 m->addAtom(new Atom(5), true, true);
645 m->addAtom(new Atom(6), true, true);
646 m->addAtom(new Atom(6), true, true);
647 m->addAtom(new Atom(6), true, true);
648 m->addAtom(new Atom(6), true, true);
649 m->addBond(0, 1, Bond::SINGLE);
650 m->addBond(0, 2, Bond::SINGLE);
651 m->addBond(0, 3, Bond::SINGLE);
652 m->addBond(0, 4, Bond::SINGLE);
653 m->getAtomWithIdx(0)->setFormalCharge(-1);
654 MolOps::sanitizeMol(*m);
655 TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == -1);
656 TEST_ASSERT(m->getAtomWithIdx(0)->getExplicitValence() == 4);
657 TEST_ASSERT(m->getAtomWithIdx(0)->getNumImplicitHs() == 0);
658 delete m;
659 }
660
661 {
662 auto *m = new RWMol();
663 m->addAtom(new Atom(5), true, true);
664 m->addAtom(new Atom(6), true, true);
665 m->addAtom(new Atom(6), true, true);
666 m->addAtom(new Atom(6), true, true);
667 m->addAtom(new Atom(6), true, true);
668 m->addBond(0, 1, Bond::SINGLE);
669 m->addBond(0, 2, Bond::SINGLE);
670 m->addBond(0, 3, Bond::SINGLE);
671 m->addBond(0, 4, Bond::SINGLE);
672 bool ok = false;
673 try {
674 MolOps::sanitizeMol(*m);
675 } catch (MolSanitizeException &) {
676 ok = true;
677 }
678 TEST_ASSERT(ok);
679 delete m;
680 }
681
682 {
683 auto *m = new RWMol();
684 m->addAtom(new Atom(5), true, true);
685 m->addAtom(new Atom(6), true, true);
686 m->addAtom(new Atom(6), true, true);
687 m->addAtom(new Atom(6), true, true);
688 m->addAtom(new Atom(6), true, true);
689 m->addBond(0, 1, Bond::SINGLE);
690 m->addBond(0, 2, Bond::SINGLE);
691 m->addBond(0, 3, Bond::SINGLE);
692 m->addBond(0, 4, Bond::SINGLE);
693 m->getAtomWithIdx(0)->setFormalCharge(+1);
694 bool ok = false;
695 try {
696 MolOps::sanitizeMol(*m);
697 } catch (MolSanitizeException &) {
698 ok = true;
699 }
700 TEST_ASSERT(ok);
701 delete m;
702 }
703
704 {
705 auto *m = new RWMol();
706 m->addAtom(new Atom(5), true, true);
707 m->addAtom(new Atom(6), true, true);
708 m->addAtom(new Atom(6), true, true);
709 m->addBond(0, 1, Bond::SINGLE);
710 m->addBond(0, 2, Bond::SINGLE);
711 m->getAtomWithIdx(0)->setFormalCharge(+1);
712 MolOps::sanitizeMol(*m);
713 TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == 1);
714 TEST_ASSERT(m->getAtomWithIdx(0)->getExplicitValence() == 2);
715 TEST_ASSERT(m->getAtomWithIdx(0)->getNumImplicitHs() == 0);
716 delete m;
717 }
718
719 {
720 auto *m = new RWMol();
721 m->addAtom(new Atom(5), true, true);
722 m->addAtom(new Atom(6), true, true);
723 m->addAtom(new Atom(6), true, true);
724 m->addAtom(new Atom(6), true, true);
725 m->addBond(0, 1, Bond::SINGLE);
726 m->addBond(0, 2, Bond::SINGLE);
727 m->addBond(0, 3, Bond::SINGLE);
728 m->getAtomWithIdx(0)->setFormalCharge(-1);
729 MolOps::sanitizeMol(*m);
730 TEST_ASSERT(m->getAtomWithIdx(0)->getFormalCharge() == -1);
731 TEST_ASSERT(m->getAtomWithIdx(0)->getExplicitValence() == 3);
732 TEST_ASSERT(m->getAtomWithIdx(0)->getNumImplicitHs() == 1);
733 TEST_ASSERT(m->getAtomWithIdx(0)->getExplicitValence() +
734 m->getAtomWithIdx(0)->getImplicitValence() ==
735 rdcast<int>(m->getAtomWithIdx(0)->getTotalValence()));
736 TEST_ASSERT(m->getAtomWithIdx(1)->getExplicitValence() +
737 m->getAtomWithIdx(1)->getImplicitValence() ==
738 rdcast<int>(m->getAtomWithIdx(1)->getTotalValence()));
739 TEST_ASSERT(m->getAtomWithIdx(2)->getExplicitValence() +
740 m->getAtomWithIdx(2)->getImplicitValence() ==
741 rdcast<int>(m->getAtomWithIdx(2)->getTotalValence()));
742 TEST_ASSERT(m->getAtomWithIdx(3)->getExplicitValence() +
743 m->getAtomWithIdx(3)->getImplicitValence() ==
744 rdcast<int>(m->getAtomWithIdx(3)->getTotalValence()));
745 delete m;
746 }
747
748 BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
749 }
750
testIssue2840217()751 void testIssue2840217() {
752 BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl;
753 BOOST_LOG(rdInfoLog) << "Testing Issue 2840217" << std::endl;
754
755 {
756 auto *m = new RWMol();
757 for (unsigned int i = 0; i < 200; ++i) {
758 m->addAtom(new Atom(6), true, true);
759 m->addAtom(new Atom(6), true, true);
760 m->addAtom(new Atom(6), true, true);
761 m->addAtom(new Atom(6), true, true);
762 m->addAtom(new Atom(6), true, true);
763 m->addAtom(new Atom(6), true, true);
764 for (unsigned int j = 0; j < 5; ++j) {
765 m->addBond(i * 6 + j, i * 6 + j + 1, Bond::AROMATIC);
766 }
767 m->addBond(i * 6, i * 6 + 5, Bond::AROMATIC);
768 }
769 TEST_ASSERT(m->getNumBonds() == 1200);
770 MolOps::sanitizeMol(*m);
771 TEST_ASSERT(m->getNumAtoms() == 1200);
772 delete m;
773 }
774
775 BOOST_LOG(rdInfoLog) << "\tdone" << std::endl;
776 }
777
test1()778 void test1() {
779 {
780 RWMol m;
781 auto *newAtom = new Atom(8);
782
783 m.addAtom(newAtom, true, true);
784 CHECK_INVARIANT(m.getAtomWithIdx(0)->getIdx() == 0, "");
785 newAtom = new Atom(6);
786 m.addAtom(newAtom, true, true);
787 CHECK_INVARIANT(m.getAtomWithIdx(0)->getIdx() == 0, "");
788 CHECK_INVARIANT(m.getAtomWithIdx(1)->getIdx() == 1, "");
789
790 newAtom = new Atom(7);
791 m.addAtom(newAtom, true, true);
792 CHECK_INVARIANT(m.getAtomWithIdx(0)->getIdx() == 0, "");
793 CHECK_INVARIANT(m.getAtomWithIdx(1)->getIdx() == 1, "");
794 CHECK_INVARIANT(m.getAtomWithIdx(2)->getIdx() == 2, "");
795 CHECK_INVARIANT(
796 m.getAtomWithIdx(1)->getOwningMol().getAtomWithIdx(1)->getIdx() == 1,
797 "");
798
799 m.addBond(0, 1, Bond::SINGLE);
800 m.addBond(1, 2, Bond::DOUBLE);
801 CHECK_INVARIANT(m.getBondWithIdx(0)->getIdx() == 0, "");
802 CHECK_INVARIANT(m.getBondWithIdx(1)->getIdx() == 1, "");
803
804 CHECK_INVARIANT(m.getBondWithIdx(0)->getBondType() == Bond::SINGLE, "");
805 CHECK_INVARIANT(m.getBondWithIdx(1)->getBondType() == Bond::DOUBLE, "");
806
807 CHECK_INVARIANT(m.getBondWithIdx(0)->getBeginAtom()->getIdx() == 0, "");
808 CHECK_INVARIANT(m.getBondWithIdx(0)->getEndAtom()->getIdx() == 1, "");
809 CHECK_INVARIANT(m.getBondWithIdx(1)->getBeginAtom()->getIdx() == 1, "");
810 CHECK_INVARIANT(m.getBondWithIdx(1)->getEndAtom()->getIdx() == 2, "");
811
812 testBookmarks(m);
813
814 // Using operator<< on a non-sanitized molecule is a test of Issue156:
815 ROMol::ADJ_ITER ai1, ai2;
816 boost::tie(ai1, ai2) = m.getAtomNeighbors(m.getAtomWithIdx(1));
817 m.updatePropertyCache();
818 boost::logging::disable_logs("rdApp.info");
819 while (ai1 != ai2) {
820 BOOST_LOG(rdInfoLog) << *m.getAtomWithIdx(*ai1) << endl;
821 ai1++;
822 }
823
824 m.addAtom(new Atom(6), true, true);
825 Bond *bsp = m.createPartialBond(2);
826 m.setBondBookmark(bsp, 47);
827 m.finishPartialBond(3, 47, Bond::SINGLE);
828 m.clearBondBookmark(47);
829 BOOST_LOG(rdInfoLog) << "partial bond added:" << endl;
830 unsigned int i;
831 m.updatePropertyCache();
832 for (i = 0; i < m.getNumAtoms(); i++) {
833 Atom *a = m.getAtomWithIdx(i);
834 BOOST_LOG(rdInfoLog) << "\t" << *a << endl;
835 }
836
837 int newAtNum = m.addAtom(new Atom(6), true, true);
838 m.addBond(0, newAtNum, Bond::SINGLE);
839
840 BOOST_LOG(rdInfoLog) << "Again:" << endl;
841 m.updatePropertyCache();
842 for (i = 0; i < m.getNumAtoms(); i++) {
843 Atom *a = m.getAtomWithIdx(i);
844 BOOST_LOG(rdInfoLog) << "\t" << *a << endl;
845 }
846
847 RWMol m2;
848 m2.addAtom(new Atom(6), true, true);
849 m2.addAtom(new Atom(6), true, true);
850 // QueryAtom *qA = new QueryAtom;
851 // qA->setAtomicNum(7);
852 // m2.addAtom(qA);
853 m2.addAtom(new QueryAtom(7), true, true);
854 m2.addBond(0, 1, Bond::TRIPLE);
855 m2.addBond(1, 2, Bond::SINGLE);
856
857 m.insertMol(m2);
858 m.updatePropertyCache();
859 BOOST_LOG(rdInfoLog) << "post-insert:" << endl;
860 for (i = 0; i < m.getNumAtoms(); i++) {
861 Atom *a = m.getAtomWithIdx(i);
862 BOOST_LOG(rdInfoLog) << "\t" << *a << endl;
863 }
864
865 BOOST_LOG(rdInfoLog) << " ------------------- " << endl;
866 auto *newA = new Atom(12);
867 int newIdx = m.addAtom(newA, true, true);
868 m.addBond(newIdx - 1, newIdx, Bond::AROMATIC);
869 // m.debugMol(cout);
870 BOOST_LOG(rdInfoLog) << " trying a replace " << endl;
871 auto *repA = new Atom(22);
872 m.replaceAtom(newIdx, repA);
873 delete repA;
874 TEST_ASSERT(m.getAtomWithIdx(newIdx)->getAtomicNum() == 22);
875 auto *nbnd = new Bond(Bond::DOUBLE);
876 TEST_ASSERT(m.getBondWithIdx(m.getNumBonds() - 1)->getBondType() ==
877 Bond::AROMATIC);
878 m.replaceBond(m.getNumBonds() - 1, nbnd);
879 m.debugMol(std::cerr);
880 TEST_ASSERT(m.getBondWithIdx(m.getNumBonds() - 1)->getBondType() ==
881 nbnd->getBondType());
882 delete nbnd;
883 delete bsp;
884 }
885 {
886 RWMol m;
887 m.addAtom(new Atom(6), true, true);
888 m.addAtom(new Atom(6), true, true);
889 m.addBond(0, 1, Bond::SINGLE);
890 auto *conf = new Conformer(m.getNumAtoms());
891 m.addConformer(conf);
892 m.getConformer().setAtomPos(0, RDGeom::Point3D(1.0, 0.0, 0.0));
893 m.getConformer().setAtomPos(1, RDGeom::Point3D(0.0, 1.0, 0.0));
894
895 RWMol m2;
896 // insert molecule without a conf:
897 m2.addAtom(new Atom(6), true, true);
898 m.insertMol(m2);
899 TEST_ASSERT(m.getConformer().getNumAtoms() == m.getNumAtoms());
900 TEST_ASSERT(feq(m.getConformer().getAtomPos(2).x, 0.0));
901 TEST_ASSERT(feq(m.getConformer().getAtomPos(2).y, 0.0));
902 TEST_ASSERT(feq(m.getConformer().getAtomPos(2).z, 0.0));
903
904 // insert molecule with a conf:
905 conf = new Conformer(m2.getNumAtoms());
906 m2.addConformer(conf);
907 m2.getConformer().setAtomPos(0, RDGeom::Point3D(1.0, 1.0, 0.0));
908 m.insertMol(m2);
909 TEST_ASSERT(m.getConformer().getNumAtoms() == m.getNumAtoms());
910 TEST_ASSERT(feq(m.getConformer().getAtomPos(2).x, 0.0));
911 TEST_ASSERT(feq(m.getConformer().getAtomPos(2).y, 0.0));
912 TEST_ASSERT(feq(m.getConformer().getAtomPos(2).z, 0.0));
913 TEST_ASSERT(feq(m.getConformer().getAtomPos(3).x, 1.0));
914 TEST_ASSERT(feq(m.getConformer().getAtomPos(3).y, 1.0));
915 TEST_ASSERT(feq(m.getConformer().getAtomPos(3).z, 0.0));
916 }
917 {
918 // start with a molecule with no conf
919 RWMol m;
920 m.addAtom(new Atom(6), true, true);
921 m.addAtom(new Atom(6), true, true);
922 m.addBond(0, 1, Bond::SINGLE);
923 TEST_ASSERT(m.getNumConformers() == 0);
924
925 RWMol m2;
926 // insert molecule without a conf:
927 m2.addAtom(new Atom(6), true, true);
928 m.insertMol(m2);
929 TEST_ASSERT(m.getNumConformers() == 0);
930
931 // insert molecule with a conf:
932 auto *conf = new Conformer(m2.getNumAtoms());
933 m2.addConformer(conf);
934 m2.getConformer().setAtomPos(0, RDGeom::Point3D(1.0, 1.0, 0.0));
935 m.insertMol(m2);
936 TEST_ASSERT(m.getNumConformers() == 1);
937 TEST_ASSERT(m.getConformer().getNumAtoms() == m.getNumAtoms());
938 TEST_ASSERT(feq(m.getConformer().getAtomPos(0).x, 0.0));
939 TEST_ASSERT(feq(m.getConformer().getAtomPos(0).y, 0.0));
940 TEST_ASSERT(feq(m.getConformer().getAtomPos(0).z, 0.0));
941 TEST_ASSERT(feq(m.getConformer().getAtomPos(3).x, 1.0));
942 TEST_ASSERT(feq(m.getConformer().getAtomPos(3).y, 1.0));
943 TEST_ASSERT(feq(m.getConformer().getAtomPos(3).z, 0.0));
944 }
945 }
946
testPeriodicTable()947 void testPeriodicTable() {
948 BOOST_LOG(rdInfoLog) << "-----------------------\n";
949 BOOST_LOG(rdInfoLog) << "Testing properties from periodic table" << std::endl;
950
951 TEST_ASSERT(PeriodicTable::getTable()->getDefaultValence(6) == 4);
952 TEST_ASSERT(PeriodicTable::getTable()->getNouterElecs(6) == 4);
953 TEST_ASSERT(PeriodicTable::getTable()->getMostCommonIsotope(6) == 12);
954 TEST_ASSERT(PeriodicTable::getTable()->getMostCommonIsotopeMass(6) == 12.0);
955 TEST_ASSERT(PeriodicTable::getTable()->getMostCommonIsotopeMass(6) == 12.0);
956 TEST_ASSERT(feq(PeriodicTable::getTable()->getMostCommonIsotopeMass(4),
957 9.0122, 1e-4));
958 TEST_ASSERT(feq(PeriodicTable::getTable()->getRb0(6), 0.77, 1e-2));
959
960 TEST_ASSERT(PeriodicTable::getTable()->getDefaultValence(26) == -1);
961 TEST_ASSERT(PeriodicTable::getTable()->getDefaultValence(57) == -1);
962
963 // this was sf.net issue 269
964 int anum;
965 anum = PeriodicTable::getTable()->getAtomicNumber("C");
966 TEST_ASSERT(anum == 6);
967 try {
968 anum = PeriodicTable::getTable()->getAtomicNumber("Xx");
969 } catch (...) {
970 anum = -1;
971 }
972 TEST_ASSERT(anum == -1);
973
974 BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
975 }
976
testAddAtomWithConf()977 void testAddAtomWithConf() {
978 BOOST_LOG(rdInfoLog) << "-----------------------\n";
979 BOOST_LOG(rdInfoLog) << "Testing issue 264: adding atoms to molecules that "
980 "already have conformers"
981 << std::endl;
982 {
983 RWMol m;
984
985 m.addAtom(new Atom(6), true, true);
986 m.addAtom(new Atom(6), true, true);
987
988 auto *conf = new Conformer(m.getNumAtoms());
989 m.addConformer(conf);
990
991 m.addAtom(new Atom(6), true, true);
992 TEST_ASSERT(m.getConformer().getNumAtoms() == m.getNumAtoms());
993 }
994 {
995 RWMol m;
996
997 m.addAtom(new Atom(6), true, true);
998 m.addAtom(new Atom(6), true, true);
999
1000 auto *conf = new Conformer(m.getNumAtoms());
1001 m.addConformer(conf);
1002
1003 m.addAtom();
1004 TEST_ASSERT(m.getConformer().getNumAtoms() == m.getNumAtoms());
1005 }
1006 { // make sure things are ok even if there is no conformer
1007 RWMol m;
1008
1009 m.addAtom(new Atom(6), true, true);
1010 m.addAtom(new Atom(6), true, true);
1011 m.addAtom(new Atom(6), true, true);
1012 TEST_ASSERT(m.getNumConformers() == 0);
1013 }
1014
1015 BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
1016 }
1017
testIssue267()1018 void testIssue267() {
1019 BOOST_LOG(rdInfoLog) << "-----------------------\n";
1020 BOOST_LOG(rdInfoLog) << "Testing issue 267: default valence of *"
1021 << std::endl;
1022 {
1023 RWMol m;
1024
1025 m.addAtom(new Atom(0), true, true);
1026 m.updatePropertyCache();
1027
1028 TEST_ASSERT(m.getAtomWithIdx(0)->getImplicitValence() == 0);
1029 }
1030 {
1031 RWMol m;
1032
1033 m.addAtom(new Atom(0), true, true);
1034 for (unsigned int i = 0; i < 8; ++i) {
1035 m.addAtom(new Atom(1), true, true);
1036 m.addBond(0, i + 1, Bond::SINGLE);
1037 }
1038 m.updatePropertyCache();
1039 }
1040 BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
1041 }
1042
testIssue284()1043 void testIssue284() {
1044 BOOST_LOG(rdInfoLog) << "-----------------------\n";
1045 BOOST_LOG(rdInfoLog) << "Testing issue 284: removeBond not updating indices"
1046 << std::endl;
1047 {
1048 RWMol m;
1049
1050 m.addAtom(new Atom(6), true, true);
1051 m.addAtom(new Atom(6), true, true);
1052 m.addAtom(new Atom(6), true, true);
1053 m.addBond(0, 1, Bond::SINGLE);
1054 m.addBond(1, 2, Bond::SINGLE);
1055 m.updatePropertyCache();
1056 TEST_ASSERT(m.getBondBetweenAtoms(0, 1)->getIdx() == 0);
1057 TEST_ASSERT(m.getBondBetweenAtoms(1, 2)->getIdx() == 1);
1058 m.removeBond(0, 1);
1059 TEST_ASSERT(!m.getBondBetweenAtoms(0, 1));
1060 TEST_ASSERT(m.getBondBetweenAtoms(1, 2)->getIdx() == 0);
1061 }
1062 BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
1063 }
1064
testAtomResidues()1065 void testAtomResidues() {
1066 BOOST_LOG(rdInfoLog) << "-----------------------\n";
1067 BOOST_LOG(rdInfoLog) << "Testing residue information handling on atoms"
1068 << std::endl;
1069 {
1070 auto *m = new RWMol();
1071
1072 m->addAtom(new Atom(6), true, true);
1073 m->addAtom(new Atom(6), true, true);
1074 m->addBond(0, 1, Bond::SINGLE);
1075 m->addAtom(new Atom(6), true, true);
1076 m->addBond(1, 2, Bond::SINGLE);
1077 m->addAtom(new Atom(6), true, true);
1078 m->addBond(2, 3, Bond::SINGLE);
1079
1080 TEST_ASSERT(!(m->getAtomWithIdx(0)->getMonomerInfo()));
1081 TEST_ASSERT(!(m->getAtomWithIdx(1)->getMonomerInfo()));
1082 TEST_ASSERT(!(m->getAtomWithIdx(2)->getMonomerInfo()));
1083 TEST_ASSERT(!(m->getAtomWithIdx(3)->getMonomerInfo()));
1084
1085 m->getAtomWithIdx(0)->setMonomerInfo(
1086 new AtomMonomerInfo(AtomMonomerInfo::OTHER, "m1"));
1087 TEST_ASSERT((m->getAtomWithIdx(0)->getMonomerInfo()));
1088 TEST_ASSERT(m->getAtomWithIdx(0)->getMonomerInfo()->getName() == "m1");
1089
1090 m->getAtomWithIdx(1)->setMonomerInfo(new AtomPDBResidueInfo("Ca", 3));
1091 TEST_ASSERT((m->getAtomWithIdx(1)->getMonomerInfo()));
1092 TEST_ASSERT(m->getAtomWithIdx(1)->getMonomerInfo()->getName() == "Ca");
1093 TEST_ASSERT(static_cast<const AtomPDBResidueInfo *>(
1094 m->getAtomWithIdx(1)->getMonomerInfo())
1095 ->getSerialNumber() == 3);
1096
1097 auto *m2 = new RWMol(*m);
1098 delete m;
1099
1100 TEST_ASSERT((m2->getAtomWithIdx(0)->getMonomerInfo()));
1101 TEST_ASSERT(m2->getAtomWithIdx(0)->getMonomerInfo()->getName() == "m1");
1102 TEST_ASSERT((m2->getAtomWithIdx(1)->getMonomerInfo()));
1103 TEST_ASSERT(m2->getAtomWithIdx(1)->getMonomerInfo()->getName() == "Ca");
1104 TEST_ASSERT(static_cast<const AtomPDBResidueInfo *>(
1105 m2->getAtomWithIdx(1)->getMonomerInfo())
1106 ->getSerialNumber() == 3);
1107 TEST_ASSERT(!(m2->getAtomWithIdx(2)->getMonomerInfo()));
1108 TEST_ASSERT(!(m2->getAtomWithIdx(3)->getMonomerInfo()));
1109 delete m2;
1110 }
1111 BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
1112 }
1113
testNeedsUpdatePropertyCache()1114 void testNeedsUpdatePropertyCache() {
1115 BOOST_LOG(rdInfoLog) << "-----------------------\n";
1116 BOOST_LOG(rdInfoLog) << "Testing function needsUpdatePropertyCache"
1117 << std::endl;
1118 {
1119 RWMol m;
1120
1121 m.addAtom(new Atom(0), true, true);
1122 TEST_ASSERT(m.needsUpdatePropertyCache() == true);
1123 m.updatePropertyCache();
1124
1125 TEST_ASSERT(m.getAtomWithIdx(0)->getImplicitValence() == 0);
1126 TEST_ASSERT(m.needsUpdatePropertyCache() == false);
1127 }
1128 {
1129 RWMol m;
1130
1131 m.addAtom(new Atom(6), true, true);
1132 for (ROMol::AtomIterator atomIt = m.beginAtoms(); atomIt != m.endAtoms();
1133 ++atomIt) {
1134 (*atomIt)->calcExplicitValence(false);
1135 (*atomIt)->calcImplicitValence(false);
1136 }
1137 m.addAtom(new Atom(6), true, true);
1138 m.addBond(0, 1, Bond::SINGLE);
1139 TEST_ASSERT(m.needsUpdatePropertyCache() == true);
1140 m.updatePropertyCache();
1141 TEST_ASSERT(m.needsUpdatePropertyCache() == false);
1142 }
1143 {
1144 RWMol m;
1145 m.addAtom(new Atom(6), true, true);
1146 m.getAtomWithIdx(0)->calcExplicitValence(false);
1147 TEST_ASSERT(m.getAtomWithIdx(0)->needsUpdatePropertyCache());
1148 m.getAtomWithIdx(0)->setNoImplicit(true);
1149 TEST_ASSERT(!m.getAtomWithIdx(0)->needsUpdatePropertyCache());
1150 }
1151 BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
1152 }
1153
1154 namespace {
qhelper(Atom::QUERYATOM_QUERY * q,unsigned int depth=0)1155 std::string qhelper(Atom::QUERYATOM_QUERY *q, unsigned int depth = 0) {
1156 std::string res = "";
1157 if (q) {
1158 for (unsigned int i = 0; i < depth; ++i) {
1159 res += " ";
1160 }
1161 res += q->getFullDescription() + "\n";
1162 for (auto ci = q->beginChildren(); ci != q->endChildren(); ++ci) {
1163 res += qhelper((*ci).get(), depth + 1);
1164 }
1165 }
1166 return res;
1167 }
1168 } // namespace
1169
1170 const char *m_als_mol =
1171 "\n"
1172 " Marvin 08200814552D \n"
1173 "\n"
1174 " 9 8 0 0 0 0 999 V2000\n"
1175 " -1.9152 1.6205 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n"
1176 " -1.0902 1.6205 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n"
1177 " -0.5068 2.2039 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n"
1178 " -2.3277 0.9061 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n"
1179 " -2.3277 2.3350 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n"
1180 " -3.1527 2.3350 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n"
1181 " -3.6830 2.8727 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n"
1182 " -3.1527 0.9061 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n"
1183 " -3.6771 0.2814 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n"
1184 " 1 2 2 0 0 0 0\n"
1185 " 2 3 1 0 0 0 0\n"
1186 " 1 4 1 0 0 0 0\n"
1187 " 1 5 1 0 0 0 0\n"
1188 " 5 6 2 0 0 0 0\n"
1189 " 6 7 1 0 0 0 0\n"
1190 " 4 8 2 0 0 0 0\n"
1191 " 8 9 1 0 0 0 0\n"
1192 "M ALS 4 2 F O Cl \n"
1193 "M END\n";
1194
testAtomListLineRoundTrip()1195 void testAtomListLineRoundTrip() {
1196 BOOST_LOG(rdInfoLog) << "-----------------------\n";
1197 BOOST_LOG(rdInfoLog) << "Test AtomListLine RoundTrip" << std::endl;
1198 std::string rdbase = getenv("RDBASE");
1199 std::string fName = rdbase + "/Code/GraphMol/test_data/m_als_round_trip.mol";
1200 const bool sanitize = false;
1201 const bool removeHs = true;
1202 const bool strictParsing = true;
1203 unsigned int line = 0;
1204
1205 std::istringstream inStream(m_als_mol);
1206 RWMol *m =
1207 MolDataStreamToMol(inStream, line, sanitize, removeHs, strictParsing);
1208 std::string desc = qhelper(m->getAtomWithIdx(3)->getQuery());
1209 TEST_ASSERT(m);
1210 TEST_ASSERT(m->getNumAtoms() == 9);
1211
1212 std::string molblock = MolToMolBlock(*m);
1213 TEST_ASSERT(molblock.find(" ALS ") != std::string::npos);
1214 std::istringstream inStream2(molblock);
1215 RWMol *m2 =
1216 MolDataStreamToMol(inStream2, line, sanitize, removeHs, strictParsing);
1217 TEST_ASSERT(m2);
1218 TEST_ASSERT(desc == qhelper(m2->getAtomWithIdx(3)->getQuery()));
1219 Atom *cl(new Atom(17));
1220 Atom *o(new Atom(8));
1221 TEST_ASSERT(dynamic_cast<QueryAtom *>(m->getAtomWithIdx(3))->Match(cl));
1222 TEST_ASSERT(dynamic_cast<QueryAtom *>(m->getAtomWithIdx(3))->Match(o));
1223 TEST_ASSERT(dynamic_cast<QueryAtom *>(m2->getAtomWithIdx(3))->Match(cl));
1224 TEST_ASSERT(dynamic_cast<QueryAtom *>(m2->getAtomWithIdx(3))->Match(o));
1225 delete cl;
1226 delete o;
1227 delete m;
1228 delete m2;
1229 BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
1230 }
1231
testAtomListLineWithOtherQueries()1232 void testAtomListLineWithOtherQueries() {
1233 BOOST_LOG(rdInfoLog) << "-----------------------\n";
1234 BOOST_LOG(rdInfoLog) << "Test AtomListLine with other queries" << std::endl;
1235 const std::list<std::string> molblocks{R"MOL(
1236 SciTegic06022014352D
1237
1238 4 3 0 0 0 0 999 V2000
1239 14.8926 -7.5485 0.0000 N 0 3 0 0 0 0 0 0 0 1 0 0
1240 13.8697 -6.9579 0.0000 L 0 0 0 0 0 0 0 0 0 4 0 0
1241 15.9154 -6.9579 0.0000 A 0 0 0 0 0 0 0 0 0 3 0 0
1242 14.8926 -8.7296 0.0000 L 0 5 0 0 0 0 0 0 0 2 0 0
1243 2 1 5 0 0 0 2
1244 1 3 1 0 0 0 2
1245 4 1 1 0 0 0 8
1246 M CHG 2 1 1 4 -1
1247 M SUB 1 4 1
1248 M ALS 2 2 F O S
1249 M ALS 4 2 F O S
1250 M END
1251 )MOL",
1252 R"MOL(
1253 SciTegic06022014352D
1254
1255 4 3 0 0 0 0 999 V2000
1256 14.8926 -7.5485 0.0000 N 0 3 0 0 0 0 0 0 0 1 0 0
1257 13.8697 -6.9579 0.0000 L 0 0 0 0 0 0 0 0 0 4 0 0
1258 15.9154 -6.9579 0.0000 A 0 0 0 0 0 0 0 0 0 3 0 0
1259 14.8926 -8.7296 0.0000 L 0 5 0 0 0 0 0 0 0 2 0 0
1260 2 1 5 0 0 0 2
1261 1 3 1 0 0 0 2
1262 4 1 1 0 0 0 8
1263 M CHG 2 1 1 4 -1
1264 M ALS 2 2 F O S
1265 M ALS 4 2 F O S
1266 M SUB 1 4 1
1267 M END
1268 )MOL"};
1269 const bool sanitize = false;
1270 const bool removeHs = true;
1271 const bool strictParsing = true;
1272
1273 for (const auto &molblock : molblocks) {
1274 RWMOL_SPTR m(MolBlockToMol(molblock, sanitize, removeHs, strictParsing));
1275 TEST_ASSERT(m->getNumAtoms() == 4);
1276 const Atom *a = m->getAtomWithIdx(3);
1277 TEST_ASSERT(a->hasQuery());
1278 const QueryAtom *qa = dynamic_cast<const QueryAtom *>(a);
1279 TEST_ASSERT(qa);
1280 TEST_ASSERT(describeQuery(a) == R"MOL(AtomAnd
1281 AtomAnd
1282 AtomOr
1283 AtomAtomicNum 8 = val
1284 AtomAtomicNum 16 = val
1285 AtomFormalCharge -1 = val
1286 AtomExplicitDegree 1 = val
1287 )MOL");
1288 TEST_ASSERT(SmartsWrite::GetAtomSmarts(qa) == "[#8,#16;-;D1:2]");
1289 }
1290 }
1291
testReplaceChargedAtomWithQueryAtom()1292 void testReplaceChargedAtomWithQueryAtom() {
1293 BOOST_LOG(rdInfoLog) << "-----------------------\n";
1294 BOOST_LOG(rdInfoLog) << "Test replaceAtomWithQueryAtom on a charged atom"
1295 << std::endl;
1296 auto mol = "[NH3+]C"_smiles;
1297 TEST_ASSERT(mol.get());
1298 auto a = mol->getAtomWithIdx(0);
1299 TEST_ASSERT(a);
1300 const QueryAtom *qa = dynamic_cast<const QueryAtom *>(
1301 QueryOps::replaceAtomWithQueryAtom(mol.get(), a));
1302 TEST_ASSERT(qa);
1303 TEST_ASSERT(SmartsWrite::GetAtomSmarts(qa) == "[#7&+]");
1304 }
1305
testGithub608()1306 void testGithub608() {
1307 BOOST_LOG(rdInfoLog) << "-----------------------\n";
1308 BOOST_LOG(rdInfoLog) << "Test github 608: stereo bonds wrong after insertMol"
1309 << std::endl;
1310
1311 {
1312 RWMol *m = SmilesToMol("N1NN1");
1313 TEST_ASSERT(m);
1314 TEST_ASSERT(m->getNumAtoms() == 3);
1315 RWMol *f = SmilesToMol("C/C=C/C");
1316 TEST_ASSERT(f);
1317 TEST_ASSERT(f->getNumAtoms() == 4);
1318 TEST_ASSERT(f->getBondBetweenAtoms(1, 2)->getStereoAtoms().size() == 2);
1319 TEST_ASSERT(f->getBondBetweenAtoms(1, 2)->getStereoAtoms()[0] == 0);
1320 TEST_ASSERT(f->getBondBetweenAtoms(1, 2)->getStereoAtoms()[1] == 3);
1321
1322 m->insertMol(*f);
1323 TEST_ASSERT(m->getNumAtoms() == 7);
1324 TEST_ASSERT(m->getBondBetweenAtoms(4, 5)->getBondType() == Bond::DOUBLE);
1325 TEST_ASSERT(m->getBondBetweenAtoms(4, 5)->getStereoAtoms().size() == 2);
1326 TEST_ASSERT(m->getBondBetweenAtoms(4, 5)->getStereoAtoms()[0] == 3);
1327 TEST_ASSERT(m->getBondBetweenAtoms(4, 5)->getStereoAtoms()[1] == 6);
1328
1329 delete m;
1330 delete f;
1331 }
1332
1333 {
1334 INT_VECT nAtoms;
1335 RWMol *m = SmilesToMol("N1NN1");
1336 TEST_ASSERT(m);
1337 TEST_ASSERT(m->getNumAtoms() == 3);
1338 RWMol *f = SmilesToMol("C[C@]1(F)CC[C@](Cl)(Br)CC1");
1339 TEST_ASSERT(f);
1340 TEST_ASSERT(f->getNumAtoms() == 10);
1341 TEST_ASSERT(f->getAtomWithIdx(1)->getPropIfPresent(
1342 common_properties::_ringStereoAtoms, nAtoms));
1343 TEST_ASSERT(std::find(nAtoms.begin(), nAtoms.end(), 6) != nAtoms.end());
1344 m->insertMol(*f);
1345 TEST_ASSERT(m->getNumAtoms() == 13);
1346 TEST_ASSERT(m->getAtomWithIdx(4)->getPropIfPresent(
1347 common_properties::_ringStereoAtoms, nAtoms));
1348 TEST_ASSERT(std::find(nAtoms.begin(), nAtoms.end(), 9) != nAtoms.end());
1349
1350 delete m;
1351 delete f;
1352 }
1353 BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
1354 }
1355
1356 #ifdef RDK_TEST_MULTITHREADED
1357 #include <thread>
1358 #include <future>
1359 #include <RDGeneral/BoostStartInclude.h>
1360 #include <boost/dynamic_bitset.hpp>
1361 #include <RDGeneral/BoostEndInclude.h>
1362 namespace {
runblock(std::vector<const PeriodicTable * > * pts,int idx)1363 void runblock(std::vector<const PeriodicTable *> *pts, int idx) {
1364 const PeriodicTable *pt = PeriodicTable::getTable();
1365 (*pts)[idx] = pt;
1366 TEST_ASSERT(pt->getAtomicNumber("C") == 6);
1367 TEST_ASSERT(pt->getAtomicNumber("N") == 7);
1368 TEST_ASSERT(pt->getAtomicNumber("O") == 8);
1369 };
1370 } // namespace
testGithub381()1371 void testGithub381() {
1372 BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl;
1373 BOOST_LOG(rdErrorLog)
1374 << " Test github381: thread-safe initialization of the periodic table"
1375 << std::endl;
1376
1377 std::vector<std::future<void>> tg;
1378 unsigned int count = 32;
1379 std::vector<const PeriodicTable *> pts(count);
1380 #if 1
1381 for (unsigned int i = 0; i < count; ++i) {
1382 std::cerr.flush();
1383 tg.emplace_back(std::async(std::launch::async, runblock, &pts, i));
1384 }
1385 for (auto &fut : tg) {
1386 fut.get();
1387 }
1388 TEST_ASSERT(pts[0] != nullptr);
1389 for (unsigned int i = 1; i < count; ++i) {
1390 TEST_ASSERT(pts[i] == pts[0]);
1391 }
1392 #endif
1393
1394 BOOST_LOG(rdErrorLog) << " done" << std::endl;
1395 }
1396 #else
testGithub381()1397 void testGithub381() {}
1398 #endif
1399
testGithub1041()1400 void testGithub1041() {
1401 BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl;
1402 BOOST_LOG(rdErrorLog) << " Test github1041: Segfault for atom with no "
1403 "owner (expect some warnings)"
1404 << std::endl;
1405 {
1406 Atom at(6);
1407 bool ok = false;
1408 try {
1409 at.getOwningMol();
1410 } catch (const Invar::Invariant &) {
1411 ok = true;
1412 }
1413 TEST_ASSERT(ok);
1414 }
1415 {
1416 Bond b;
1417 bool ok = false;
1418 try {
1419 b.getOwningMol();
1420 } catch (const Invar::Invariant &) {
1421 ok = true;
1422 }
1423 TEST_ASSERT(ok);
1424 }
1425 BOOST_LOG(rdErrorLog) << " done" << std::endl;
1426 }
1427
testGithub1453()1428 void testGithub1453() {
1429 BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl;
1430 BOOST_LOG(rdErrorLog)
1431 << " Test github1453: RWMol.clear() should reset the numBonds count."
1432 << std::endl;
1433
1434 RWMol m2;
1435
1436 m2.addAtom(new Atom(6), true, true);
1437 m2.addAtom(new Atom(6), true, true);
1438 m2.addBond(0, 1, Bond::TRIPLE);
1439 TEST_ASSERT(m2.getNumAtoms() == 2);
1440 TEST_ASSERT(m2.getNumBonds() == 1);
1441 m2.clear();
1442 TEST_ASSERT(m2.getNumAtoms() == 0);
1443 TEST_ASSERT(m2.getNumBonds() == 0);
1444
1445 BOOST_LOG(rdErrorLog) << " done" << std::endl;
1446 }
1447
testRanges()1448 void testRanges() {
1449 BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl;
1450 BOOST_LOG(rdErrorLog) << " Test range-based for loops." << std::endl;
1451 RWMol *m = SmilesToMol("C1CC1");
1452 TEST_ASSERT(m);
1453 TEST_ASSERT(m->getNumAtoms() == 3);
1454
1455 // For by value (ok since the atoms are pointers)
1456 unsigned int i = 0;
1457 for (auto atom : m->atoms()) {
1458 TEST_ASSERT(atom->getIdx() == i);
1459 i++;
1460 }
1461
1462 // try refs
1463 i = 0;
1464 for (auto &atom : m->atoms()) {
1465 TEST_ASSERT(atom->getIdx() == i);
1466 i++;
1467 }
1468
1469 // try const refs
1470 i = 0;
1471 for (auto const &atom : m->atoms()) {
1472 TEST_ASSERT(atom->getIdx() == i);
1473 i++;
1474 }
1475
1476 const RWMol *cm = m;
1477 i = 0;
1478 for (auto atom : cm->atoms()) {
1479 TEST_ASSERT(atom->getIdx() == i);
1480 i++;
1481 }
1482
1483 i = 0;
1484 for (auto bond : m->bonds()) {
1485 TEST_ASSERT(bond->getIdx() == i);
1486 i++;
1487 }
1488
1489 i = 0;
1490 for (auto bond : cm->bonds()) {
1491 TEST_ASSERT(bond->getIdx() == i);
1492 i++;
1493 }
1494
1495 const auto atom = m->getAtomWithIdx(0);
1496 i = 0;
1497 for (const auto &nbri :
1498 boost::make_iterator_range(m->getAtomNeighbors(atom))) {
1499 const auto &nbr = (*m)[nbri];
1500 TEST_ASSERT(nbr->getAtomicNum() == 6);
1501 i++;
1502 }
1503 TEST_ASSERT(i == 2);
1504
1505 i = 0;
1506 for (const auto &nbri : boost::make_iterator_range(m->getAtomBonds(atom))) {
1507 const auto &bnd = (*m)[nbri];
1508 TEST_ASSERT(bnd->getBondType() == Bond::SINGLE);
1509 i++;
1510 }
1511 TEST_ASSERT(i == 2);
1512
1513 // non-const versions of the same things
1514 i = 0;
1515 for (const auto &nbri :
1516 boost::make_iterator_range(m->getAtomNeighbors(atom))) {
1517 auto nbr = (*m)[nbri];
1518 TEST_ASSERT(nbr->getAtomicNum() == 6);
1519 nbr->setAtomicNum(7);
1520 nbr->setAtomicNum(6);
1521 i++;
1522 }
1523 TEST_ASSERT(i == 2);
1524
1525 i = 0;
1526 for (const auto &nbri : boost::make_iterator_range(m->getAtomBonds(atom))) {
1527 auto bnd = (*m)[nbri];
1528 TEST_ASSERT(bnd->getBondType() == Bond::SINGLE);
1529 bnd->setBondType(Bond::DOUBLE);
1530 bnd->setBondType(Bond::SINGLE);
1531 i++;
1532 }
1533 TEST_ASSERT(i == 2);
1534
1535 delete m;
1536
1537 BOOST_LOG(rdErrorLog) << " done" << std::endl;
1538 }
1539
testGithub1642()1540 void testGithub1642() {
1541 BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl;
1542 BOOST_LOG(rdErrorLog)
1543 << " Test github1642: Atom index type is too low for big molecules."
1544 << std::endl;
1545 RWMol m2;
1546
1547 unsigned int big_num_atoms = 70000;
1548 Atom *carbon = new Atom(6);
1549 for (unsigned int i = 0; i < big_num_atoms; ++i) {
1550 m2.addAtom(carbon);
1551 }
1552
1553 TEST_ASSERT(m2.getNumAtoms() == big_num_atoms);
1554
1555 for (int i = big_num_atoms; i > 0; --i) {
1556 m2.removeAtom(i - 1);
1557 }
1558 TEST_ASSERT(m2.getNumAtoms() == 0);
1559
1560 delete carbon;
1561 BOOST_LOG(rdErrorLog) << "Finished" << std::endl;
1562 }
1563
testGithub1843()1564 void testGithub1843() {
1565 BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl;
1566 BOOST_LOG(rdErrorLog)
1567 << " Test github1843: RWMol.clear() should not destroy ring pointer."
1568 << std::endl;
1569
1570 RWMol *m = SmilesToMol("N1NN1");
1571 m->clear();
1572 MolOps::sanitizeMol(*m);
1573 delete m;
1574 BOOST_LOG(rdErrorLog) << "Finished" << std::endl;
1575 }
1576
1577 // -------------------------------------------------------------------
main()1578 int main() {
1579 RDLog::InitLogs();
1580 // boost::logging::enable_logs("rdApp.info");
1581 #if 1
1582 test1();
1583 testPropLeak();
1584 testMolProps();
1585 testAtomProps();
1586 testBondProps();
1587 testMisc();
1588 testDegree();
1589 testIssue1993296();
1590 testIssue2381580();
1591 testIssue2840217();
1592 testPeriodicTable();
1593 testAddAtomWithConf();
1594 testIssue267();
1595 testIssue284();
1596 testClearMol();
1597 testAtomResidues();
1598 testNeedsUpdatePropertyCache();
1599 testGithub608();
1600 testGithub381();
1601 testGithub1041();
1602 testGithub1041();
1603 testGithub1453();
1604 testRanges();
1605 testGithub1642();
1606 testGithub1843();
1607 #endif
1608 testAtomListLineRoundTrip();
1609 testAtomListLineWithOtherQueries();
1610 testReplaceChargedAtomWithQueryAtom();
1611
1612 return 0;
1613 }
1614