1 #include "obtest.h"
2 #include <openbabel/mol.h>
3 #include <openbabel/obconversion.h>
4 #include <openbabel/phmodel.h>
5 #include <openbabel/elements.h>
6 #include <openbabel/atom.h>
7 #include <openbabel/obiter.h>
8 #include <openbabel/bond.h>
9 #include <openbabel/generic.h>
10 #include <openbabel/forcefield.h>
11
12 #include <iostream>
13 #include <string>
14 #include <vector>
15 #include <algorithm>
16
17 using namespace std;
18 using namespace OpenBabel;
19
test_Fix1912_PDBReading()20 void test_Fix1912_PDBReading()
21 {
22 // Reading from a PDB file should set the residues
23 // and mark chains as perceived
24 OBMolPtr mol = OBTestUtil::ReadFile("00T_ideal_het.pdb");
25 OB_ASSERT(mol->HasChainsPerceived());
26 OBAtom* atom = mol->GetAtom(1);
27 OBResidue* res = atom->GetResidue();
28 OB_REQUIRE(res != nullptr);
29 OB_COMPARE(res->GetAtomID(atom), " N19");
30 OB_COMPARE(res->GetChain(), 'A');
31 }
32
remove_slashr(const char * smi)33 std::string remove_slashr(const char* smi)
34 {
35 // Remove \r if present to normalise across platforms
36 std::string ans;
37 const char *p = smi;
38 while (*p) {
39 if (*p != '\r')
40 ans += *p;
41 p++;
42 }
43 return ans;
44 }
45
46 struct CdxData {
47 const char* fname;
48 const char* smi;
49 };
50
51 // Some basic reading of ChemDraw files
52 // Note that we don't correctly read radicals - TODO
53 // Also, converting ChemDraw doesn't work with the Read() interface, only Convert()
test_ChemDraw_Basic()54 void test_ChemDraw_Basic()
55 {
56 static const CdxData cdxData[] = {
57 { "ethanol.cdx", "CCO\t\n" },
58 // cyclohexane -> benzene reaction, plus another cyclohexane drawn on its own
59 { "molrxnmix.cdx", "C1CCCCC1>>c1ccccc1\t\nC1CCCCC1\t\n" },
60 { "MeCN.cdx", "CC#N\t\n"}
61 };
62
63 ios_base::openmode imode = ios_base::in | ios_base::binary;
64 unsigned int size = sizeof(cdxData) / sizeof(CdxData);
65 OBConversion conv;
66 OB_REQUIRE(conv.SetInAndOutFormats("cdx", "smi"));
67 std::stringstream outs;
68 conv.SetOutStream(&outs);
69
70 for (int i=0; i<size; ++i) {
71 std::string fname = OBTestUtil::GetFilename(cdxData[i].fname);
72 std::ifstream ifs(fname.c_str(), imode);
73 OB_REQUIRE(ifs.good());
74 conv.SetInStream(&ifs);
75 outs.str("");
76 conv.Convert();
77 std::string out = outs.str();
78 OB_COMPARE(remove_slashr(out.c_str()), cdxData[i].smi);
79 }
80 }
81
82 // A basic test of functionality
test_OBChemTsfm()83 void test_OBChemTsfm()
84 {
85 OBMol mol;
86 OBConversion conv;
87 conv.SetInFormat("smi");
88 conv.SetOutFormat("smi");
89
90 // Notes to self: Problems with OBChemTsfm:
91 // tsfm.Init("Cl[C:1]-[C:2]", "[C:1]=[C:2]"); // TODO: Need to change the API to take const char
92 // Init should wipe the state so that OBChemTsfm can safely be reused
93
94 conv.ReadString(&mol, "NCCBr");
95 OBChemTsfm tsfm;
96 std::string start("[N:1]-C-C");
97 std::string end("[N+:1]");
98 tsfm.Init(start, end);
99 tsfm.Apply(mol);
100 std::string out = conv.WriteString(&mol, true);
101 OB_COMPARE(out, "[NH3+]CCBr");
102
103 conv.ReadString(&mol, "ClCCBr");
104 start = "Cl[C:1]-[C:2]";
105 end = "[C:1]=[C:2]";
106 OBChemTsfm b;
107 b.Init(start, end);
108 b.Apply(mol);
109 out = conv.WriteString(&mol, true);
110 OB_COMPARE(out, "ClC=CBr");
111
112 conv.ReadString(&mol, "ClC(=O)[O]");
113 start = "[#6]-[OD1:1]";
114 end = "[#6]-[O-1:1]";
115 OBChemTsfm c;
116 c.Init(start, end);
117 c.Apply(mol);
118 out = conv.WriteString(&mol, true);
119 OB_COMPARE(out, "ClC(=O)[O-]");
120
121 conv.ReadString(&mol, "Cl[C]CBr");
122 start = "Cl[C:1]-[C:2]";
123 end = "[C:1]=[C:2]";
124 OBChemTsfm d;
125 d.Init(start, end);
126 d.Apply(mol);
127 out = conv.WriteString(&mol, true);
128 OB_COMPARE(out, "Cl[C]=CBr");
129 }
130
131 // Open Babel was previously disappearing triple bonds when provided with SMILES
132 // containing a triple bond in an aromatic ring
test_AromaticTripleBond()133 void test_AromaticTripleBond()
134 {
135 const char* smis[] = {
136 "CCc1n[c]#[c]n1CC2CC(C(=O)O2)(c3ccccc3)c4ccccc4",
137 "CCc1nc#cn1CC2CC(C(=O)O2)(c3ccccc3)c4ccccc4" };
138
139 OBConversion conv;
140 conv.SetInFormat("smi");
141
142 for(int i=0; i<2; ++i) {
143 OBMol mol;
144 conv.ReadString(&mol, smis[i]);
145 bool hasTripleBond = false;
146 FOR_BONDS_OF_MOL(bond, mol) {
147 if (bond->GetBondOrder()==3)
148 hasTripleBond = true;
149 }
150 OB_ASSERT(hasTripleBond);
151 }
152 }
153
154 // A segfault was occuring when a Universal SMILES was output after an InChIfied SMILES.
155 // This was due to short-circuit caching of InChIs on reading. The fix was to limit
156 // the situations when the cached value was used, but also to delete the cached value
157 // in this particular instance.
test_Issue135_UniversalSmiles()158 void test_Issue135_UniversalSmiles()
159 {
160 // Test writing U smiles after I smiles
161 OBConversion conv;
162 conv.SetInFormat("smi");
163 OBMol mol;
164 conv.ReadString(&mol, "C(=O)([O-])C(=O)O");
165 conv.SetOutFormat("smi");
166 conv.SetOptions("I", OBConversion::OUTOPTIONS);
167 std::string res = conv.WriteString(&mol, true);
168 OB_COMPARE(res, "C(=O)(C(=O)O)[O-]");
169 conv.SetOptions("U", OBConversion::OUTOPTIONS);
170 res = conv.WriteString(&mol, true);
171 OB_COMPARE(res, "C(=O)(C(=O)[O-])O");
172 }
173
174 // Reading an InChI and then adding hydrogens messed up the structure
test_Issue134_InChI_addH()175 void test_Issue134_InChI_addH()
176 {
177 OBConversion conv;
178 conv.SetInFormat("inchi");
179 OBMol mol;
180 conv.ReadString(&mol, "InChI=1S/C2H7NO/c1-2(3)4/h2,4H,3H2,1H3/t2-/m0/s1");
181 OB_ASSERT(!mol.HasData(OBGenericDataType::VirtualBondData));
182 mol.AddHydrogens();
183 conv.SetOutFormat("smi");
184 std::string res = conv.WriteString(&mol, true);
185 OB_COMPARE(res, "C[C@@H](N)O");
186 }
187
188 // Delete hydrogens should not remove charged or isotopic hydrogens or [H][H] or [Cu][H][Cu]
189 // or hydrogens with assigned atom classes
test_Issue178_DeleteHydrogens()190 void test_Issue178_DeleteHydrogens()
191 {
192 OBConversion conv;
193 conv.SetInFormat("smi");
194 OBMol mol;
195 // Test DeleteHydrogens() and DeleteNonPolarHydrogens()
196 static const char *smi[] = { "C[H]", "[H][H]", "C[1H]", "C[H]C", "C[H+]" };
197 int numHs[] = { 0, 2, 1, 1, 1 };
198 for (int i = 0; i < 5; ++i) {
199 for (int j = 0; j < 2; ++j) {
200 conv.ReadString(&mol, smi[i]);
201 if (j == 0)
202 mol.DeleteHydrogens();
203 else
204 mol.DeleteNonPolarHydrogens();
205 int myNumHs = 0;
206 FOR_ATOMS_OF_MOL(atom, mol)
207 if (atom->GetAtomicNum() == OBElements::Hydrogen)
208 myNumHs++;
209 OB_COMPARE(myNumHs, numHs[i]);
210 }
211 }
212 // Test DeletePolarHydrogens()
213 static const char *smiB[] = { "N[H]", "[H][H]", "N[1H]", "N[H]C", "N[H+]" };
214 int numHsB[] = { 0, 2, 1, 1, 1 };
215 for (int i = 0; i < 5; ++i) {
216 conv.ReadString(&mol, smiB[i]);
217 mol.DeletePolarHydrogens();
218 int myNumHs = 0;
219 FOR_ATOMS_OF_MOL(atom, mol)
220 if (atom->GetAtomicNum() == OBElements::Hydrogen)
221 myNumHs++;
222 OB_COMPARE(myNumHs, numHsB[i]);
223 }
224 // Test atom class
225 // Currently, the SMILES parser does not retain atom classes for hydrogens on reading so...
226 conv.ReadString(&mol, "C[H]");
227 OBPairInteger *ac = new OBPairInteger();
228 ac->SetAttribute("Atom Class");
229 ac->SetValue(99);
230 mol.GetAtom(2)->SetData(ac); // Assign the hydrogen (atom 2) a class of 99
231 mol.DeleteHydrogens();
232 int myNumHs = 0;
233 FOR_ATOMS_OF_MOL(atom, mol)
234 if (atom->GetAtomicNum() == OBElements::Hydrogen)
235 myNumHs++;
236 OB_COMPARE(myNumHs, 1);
237 }
238
test_Issue305_NumRotors()239 void test_Issue305_NumRotors()
240 {
241 OBMolPtr mol = OBTestUtil::ReadFile("regressiontest_numrotors.mol");
242 OB_COMPARE(mol->NumRotors(), 9); // was returning 4
243 }
244
test_PR329_Molfile_RGroups()245 void test_PR329_Molfile_RGroups()
246 {
247 // There are several way to get an R Group into a mol file
248 // 1. The existing use of atom maps on dummy atoms in SMILES
249 OBConversion conv;
250 OBMol mol;
251 conv.SetInAndOutFormats("smi", "mol");
252 conv.ReadString(&mol, "C([*:1]CO[*:2]");
253 obErrorLog.SetOutputLevel(obError); // avoid warning about no 2D or 3D coords
254 std::string molfileWithRGP = conv.WriteString(&mol);
255 obErrorLog.SetOutputLevel(obWarning);
256 OB_ASSERT( molfileWithRGP.find("R#") != std::string::npos );
257 OB_ASSERT( molfileWithRGP.find("M RGP 2 2 1 5 2") != std::string::npos); // i.e. atom 2 is labelled R1, atom 5 is labelled R2
258 // Check negative case
259 conv.ReadString(&mol, "C([*]CO[*]");
260 std::string molfileb = conv.WriteString(&mol);
261 OB_ASSERT( molfileb.find("R#") == std::string::npos );
262 OB_ASSERT( molfileb.find("M RGP") == std::string::npos);
263
264 // 2. By reading a molfile that use the R#, RGP notation
265 conv.SetInAndOutFormats("mol", "mol");
266 conv.ReadString(&mol, molfileWithRGP);
267 molfileb = conv.WriteString(&mol);
268 OB_ASSERT( molfileb.find("R#") != std::string::npos );
269 OB_ASSERT( molfileb.find("M RGP 2 2 1 5 2") != std::string::npos); // i.e. atom 2 is labelled R1, atom 5 is labelled R2
270
271 // 3. By reading a molfile that specifies the atom alias as Rn, where n is an integer
272 std::string molfileWithAlias = "\n"
273 " OpenBabel07211621152D\n"
274 "\n"
275 " 2 1 0 0 0 0 0 0 0 0999 V2000\n"
276 " 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n"
277 " 0.0000 1.0000 0.0000 * 0 0 0 0 0 0 0 0 0 0 0 0\n"
278 " 1 2 1 0 0 0 0\n"
279 "A 2\n"
280 "R1\n"
281 "M END";
282 conv.SetInAndOutFormats("mol", "mol");
283 conv.ReadString(&mol, molfileWithAlias);
284 std::string molfile = conv.WriteString(&mol);
285 OB_ASSERT( molfile.find("R#") != std::string::npos );
286 OB_ASSERT( molfile.find("M RGP 1 2 1") != std::string::npos); // i.e. atom 2 is labelled R1
287 // Check negative case
288 molfileWithAlias = "\n"
289 " OpenBabel07211621152D\n"
290 "\n"
291 " 2 1 0 0 0 0 0 0 0 0999 V2000\n"
292 " 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n"
293 " 0.0000 1.0000 0.0000 * 0 0 0 0 0 0 0 0 0 0 0 0\n"
294 " 1 2 1 0 0 0 0\n"
295 "A 2\n"
296 "R\n"
297 "M END";
298 conv.SetInAndOutFormats("mol", "mol");
299 obErrorLog.SetOutputLevel(obError); // avoid warning "Alias R was not chemically interpreted"
300 conv.ReadString(&mol, molfileWithAlias);
301 obErrorLog.SetOutputLevel(obWarning);
302 molfile = conv.WriteString(&mol);
303 OB_ASSERT( molfile.find("R#") == std::string::npos );
304 OB_ASSERT( molfile.find("M RGP") == std::string::npos);
305
306 // 4. By reading a molfile that specifies the element name as R1, etc.
307 std::string molfileWithRGroupElementName = "\n"
308 " OpenBabel07211621152D\n"
309 "\n"
310 " 2 1 0 0 0 0 0 0 0 0999 V2000\n"
311 " 1.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n"
312 " 0.0000 1.0000 0.0000 R1 0 0 0 0 0 0 0 0 0 0 0 0\n"
313 " 1 2 1 0 0 0 0\n"
314 "M END";
315 conv.SetInAndOutFormats("mol", "mol");
316 conv.ReadString(&mol, molfileWithRGroupElementName);
317 molfile = conv.WriteString(&mol);
318 OB_ASSERT( molfile.find("R#") != std::string::npos );
319 OB_ASSERT( molfile.find("M RGP 1 2 1") != std::string::npos); // i.e. atom 2 is labelled R1
320 }
321
322 struct SmilesData {
323 const char* inp;
324 const char* out;
325 const char* out_hoption; // if you specify -xh, i.e. "output explicit Hydrogens as such"
326 const char* out_addh_hoption; // if you add hydrogens and then specify "-xh"
327 const char* out_soption; // if you specify -xs, create SMARTS for substructure searching
328 };
329
test_SMILES_Valence()330 void test_SMILES_Valence()
331 {
332 static const SmilesData smilesData[] = {
333 { "[H]", "", "", "", "[#1]" }, // SMARTS perhaps should be [*H], but not implemented at the moment
334 { "[H][H]", "", "", "","[#1][#1]" },
335 { "[HH]", "", "", "[H][H]", "[#1]" },
336 { "C", "", "", "C([H])([H])([H])[H]", "" },
337 { "[C]", "", "", "", "C" },
338 { "[CH]", "", "", "[C][H]", "C" },
339 { "[CH3]", "", "", "[C]([H])([H])[H]", "C" },
340 { "[CH4]", "C", "C", "C([H])([H])([H])[H]", "C" },
341 { "[CH5]", "", "", "[C]([H])([H])([H])([H])[H]", "C" },
342 { "C[H]", "C", "", "C([H])([H])([H])[H]", "[C!H0]" },
343 { "[C][H]", "[CH]", "", "", "[C!H0]" },
344 { "[CH3][H]", "C", "C[H]", "C([H])([H])([H])[H]", "[C!H0]" },
345 { "[CH2]([H])[H]", "C", "C([H])[H]", "C([H])([H])([H])[H]", "[C!H0!H1]" },
346 { "[U][H]", "[UH]", "", "", "[U!H0]" },
347 { "[UH2]", "", "", "[U]([H])[H]", "[U]" },
348 { "[C@@H](Br)(Cl)I", "", "", "[C@](Br)(Cl)(I)[H]", "[C](Br)(Cl)I" }, // Note: if OB supported it, SMARTS should be [C@@?](Br)(Cl)I
349 { "Br[C@@H](Cl)I", "", "", "Br[C@@](Cl)(I)[H]", "Br[C](Cl)I" }, // Note: if OB supported it, SMARTS should be Br[C@@?](Cl)I
350 { "[C@@](F)(Br)(Cl)I", "", "", "", "" },
351 { "F[C@@](Br)(Cl)I", "", "", "", "" },
352 { "[H][C@@](Br)(Cl)I", "[C@@H](Br)(Cl)I", "", "", "[C@@H](Br)(Cl)I" },
353 { "C[H:1]", "C", "C[H]", "C([H])([H])([H])[H]", "[C!H0]" }, // atom class only shown with -xa
354 { "C[2H]", "", "", "C([2H])([H])([H])[H]", "C[2#1]" },
355 { "c1ccccc1", "", "", "c1(c(c(c(c(c1[H])[H])[H])[H])[H])[H]", "" },
356 { "c1cnccc1", "", "", "c1(c(nc(c(c1[H])[H])[H])[H])[H]", "" },
357 { "c1c[nH]cc1", "", "", "c1(c(n(c(c1[H])[H])[H])[H])[H]", "c1cncc1" },
358 { "F[I]F", "", "", "", "FIF" },
359 };
360 unsigned int size = (unsigned int)(sizeof(smilesData) / sizeof(smilesData[0]));
361 for (unsigned int rep = 0; rep < 4; ++rep) {
362 printf("Rep: %d\n", rep);
363 OBConversion conv;
364 OB_ASSERT(conv.SetInAndOutFormats("smi", "smi"));
365 switch (rep) {
366 case 1: case 2: conv.SetOptions("h", conv.OUTOPTIONS); break;
367 case 3: conv.SetOptions("s", conv.OUTOPTIONS); break;
368 }
369 for (unsigned int i = 0; i < size; ++i) {
370 OBMol mol;
371 OB_ASSERT(conv.ReadString(&mol, smilesData[i].inp));
372 if (rep == 2)
373 mol.AddHydrogens();
374 std::string out = conv.WriteString(&mol, true);
375 const char* mout;
376 switch (rep) {
377 case 0: mout = smilesData[i].out; break;
378 case 1: mout = smilesData[i].out_hoption; break;
379 case 2: mout = smilesData[i].out_addh_hoption; break;
380 case 3: mout = smilesData[i].out_soption; break;
381 }
382 std::string ans = mout[0] ? mout : smilesData[i].inp;
383 printf(" %d %s --> %s (%s)\n", i, smilesData[i].inp, ans.c_str(), out.c_str());
384 OB_COMPARE(out, ans);
385 }
386 }
387
388 OBConversion conv;
389 OB_ASSERT(conv.SetInAndOutFormats("smi", "smi"));
390 conv.SetOptions("ah", conv.OUTOPTIONS); // write out alias explicitly
391 OBMol mol;
392 conv.ReadString(&mol, "C[H:1]");
393 OB_COMPARE(conv.WriteString(&mol, true), "C[H:1]");
394 }
395
396 //make sure insertion code gets copied (it wasn't)
test_insertioncode()397 void test_insertioncode()
398 {
399 const char* pdb = "ATOM 266 HB2 ASP L 14 -2.604 8.021 19.867 1.00 0.00 H\n\
400 ATOM 267 CG ASP L 14 -2.280 6.992 21.697 1.00 18.10 C\n\
401 ATOM 268 OD1 ASP L 14 -1.109 7.431 21.698 1.00 18.97 O\n\
402 ATOM 269 OD2 ASP L 14 -2.735 6.263 22.603 1.00 19.18 O\n\
403 ATOM 270 N LYS L 14A -5.804 6.060 21.469 1.00 20.85 N\n\
404 ATOM 271 H LYS L 14A -5.589 5.759 20.497 1.00 0.00 H\n\
405 ATOM 272 CA LYS L 14A -6.654 5.209 22.296 1.00 22.86 C\n\
406 ATOM 273 HA LYS L 14A -7.392 5.923 22.662 1.00 0.00 H\n\
407 ATOM 274 C LYS L 14A -6.108 4.607 23.591 1.00 21.70 C\n\
408 ATOM 275 O LYS L 14A -6.892 4.228 24.455 1.00 21.72 O\n";
409
410 OBConversion conv;
411 OB_ASSERT(conv.SetInAndOutFormats("pdb", "pdb"));
412 OBMol mol;
413 conv.ReadString(&mol, pdb);
414 OBMol mol2;
415 mol2 = mol;
416 char i = mol2.GetResidue(1)->GetInsertionCode();
417 OB_COMPARE(i, 'A');
418 }
419
420 //make sure icode is read by pdbqt
test_insertioncode_pdbqt()421 void test_insertioncode_pdbqt()
422 {
423 const char* pdb = "ATOM 266 HB2 ASP L 14 -2.604 8.021 19.867 1.00 0.00 H\n\
424 ATOM 267 CG ASP L 14 -2.280 6.992 21.697 1.00 18.10 C\n\
425 ATOM 268 OD1 ASP L 14 -1.109 7.431 21.698 1.00 18.97 O\n\
426 ATOM 269 OD2 ASP L 14 -2.735 6.263 22.603 1.00 19.18 O\n\
427 ATOM 270 N LYS L 14A -5.804 6.060 21.469 1.00 20.85 N\n\
428 ATOM 271 H LYS L 14A -5.589 5.759 20.497 1.00 0.00 H\n\
429 ATOM 272 CA LYS L 14A -6.654 5.209 22.296 1.00 22.86 C\n\
430 ATOM 273 HA LYS L 14A -7.392 5.923 22.662 1.00 0.00 H\n\
431 ATOM 274 C LYS L 14A -6.108 4.607 23.591 1.00 21.70 C\n\
432 ATOM 275 O LYS L 14A -6.892 4.228 24.455 1.00 21.72 O\n";
433
434 OBConversion conv;
435 OB_ASSERT(conv.SetInAndOutFormats("pdbqt", "pdbqt"));
436 OBMol mol;
437 conv.ReadString(&mol, pdb);
438 OBMol mol2;
439 mol2 = mol;
440 char i = mol2.GetResidue(1)->GetInsertionCode();
441 OB_COMPARE(i, 'A');
442 }
443
444 // https://github.com/openbabel/openbabel/issues/1794
test_github_issue_1794()445 void test_github_issue_1794()
446 {
447 OBMol mol;
448 OBConversion conv;
449 conv.SetInFormat("smi");
450 conv.ReadString(&mol, "CC[2H]");
451
452 OBForceField* pFF = OBForceField::FindForceField("UFF");
453 OB_REQUIRE(pFF);
454
455 OB_ASSERT(pFF->Setup(mol));
456 }
457
test_github_issue_2111_impl(const std::string & smiles)458 void test_github_issue_2111_impl(const std::string &smiles)
459 {
460 OBMol mol;
461 OBConversion conv;
462 conv.SetInAndOutFormats("smi", "inchi");
463
464 conv.ReadString(&mol, smiles);
465 mol.DeleteHydrogens();
466 conv.WriteString(&mol);
467 }
468
469 // https://github.com/openbabel/openbabel/issues/2111
test_github_issue_2111()470 void test_github_issue_2111()
471 {
472 test_github_issue_2111_impl("[H][C@@H](I)F"); // tetrahedral with 2 implicit refs
473 test_github_issue_2111_impl("[H]/N=C/F"); // cis/trans with 2 implicit refs on the left
474 test_github_issue_2111_impl("F/N=C/[H]"); // cis/trans with 2 implicit refs on the right
475
476 //
477 // Tetrahedral
478 //
479
480 // example from bug report
481 test_github_issue_2111_impl("[C@@H]12C[C@H](OCC3=CC=CC=C3)[C@@H](COCC3=CC=CC=C3)[C@]1([H])O2");
482
483 // implicit ref in all positions
484 test_github_issue_2111_impl("[H][C@](C)(F)I");
485 test_github_issue_2111_impl("C[C@]([H])(F)I");
486 test_github_issue_2111_impl("C[C@](F)([H])I");
487 test_github_issue_2111_impl("C[C@](F)(I)[H]");
488
489 //
490 // Cis/Trans
491 //
492
493 // implicit ref in all positions
494 test_github_issue_2111_impl("[H]/N(C)=C/F");
495 test_github_issue_2111_impl("C/N([H])=C/F");
496 test_github_issue_2111_impl("F/N=C(/[H])C");
497 test_github_issue_2111_impl("F/N=C(/C)[H]");
498 }
499
regressionstest(int argc,char * argv[])500 int regressionstest(int argc, char* argv[])
501 {
502 int defaultchoice = 1;
503
504 int choice = defaultchoice;
505
506 if (argc > 1) {
507 if(sscanf(argv[1], "%d", &choice) != 1) {
508 printf("Couldn't parse that input as a number\n");
509 return -1;
510 }
511 }
512 // Define location of file formats for testing
513 #ifdef FORMATDIR
514 char env[BUFF_SIZE];
515 snprintf(env, BUFF_SIZE, "BABEL_LIBDIR=%s", FORMATDIR);
516 putenv(env);
517 #endif
518
519 switch(choice) {
520 case 1:
521 test_Issue135_UniversalSmiles();
522 break;
523 case 221:
524 test_Issue134_InChI_addH();
525 break;
526 case 222:
527 test_Issue178_DeleteHydrogens();
528 break;
529 case 223:
530 test_Issue305_NumRotors();
531 break;
532 case 224:
533 test_PR329_Molfile_RGroups();
534 break;
535 case 225:
536 test_AromaticTripleBond();
537 break;
538 case 226:
539 test_SMILES_Valence();
540 break;
541 case 227:
542 test_OBChemTsfm();
543 break;
544 case 228:
545 test_ChemDraw_Basic();
546 break;
547 case 240:
548 test_Fix1912_PDBReading();
549 break;
550 case 241:
551 test_insertioncode();
552 break;
553 case 242:
554 test_insertioncode_pdbqt();
555 break;
556 case 1794:
557 test_github_issue_1794();
558 break;
559 case 2111:
560 test_github_issue_2111();
561 break;
562 //case N:
563 // YOUR_TEST_HERE();
564 // Remember to update CMakeLists.txt with the number of your test
565 // break;
566 default:
567 cout << "Test number " << choice << " does not exist!\n";
568 return -1;
569 }
570
571 return 0;
572 }
573
574