1 /*
2  * Copyright (c) 2017 John Mayfield <jwmay@users.sf.net>
3  *
4  * Contact: cdk-devel@lists.sourceforge.net
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or (at
9  * your option) any later version. All we ask is that proper credit is given
10  * for our work, which includes - but is not limited to - adding the above
11  * copyright notice to the beginning of your source code files, and to any
12  * copyright notice that you may distribute with programs based on this work.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 package org.openscience.cdk.isomorphism;
25 
26 import org.junit.Test;
27 import org.openscience.cdk.Atom;
28 import org.openscience.cdk.CDKConstants;
29 import org.openscience.cdk.ReactionRole;
30 import org.openscience.cdk.config.Elements;
31 import org.openscience.cdk.graph.Cycles;
32 import org.openscience.cdk.interfaces.IAtom;
33 import org.openscience.cdk.interfaces.IAtomContainer;
34 import org.openscience.cdk.interfaces.IAtomType;
35 import org.openscience.cdk.interfaces.IBond;
36 import org.openscience.cdk.isomorphism.matchers.Expr;
37 import org.openscience.cdk.templates.TestMoleculeFactory;
38 
39 import java.util.Arrays;
40 import java.util.Collections;
41 
42 import static org.hamcrest.CoreMatchers.is;
43 import static org.junit.Assert.assertFalse;
44 import static org.junit.Assert.assertThat;
45 import static org.junit.Assert.assertTrue;
46 import static org.mockito.Mockito.mock;
47 import static org.mockito.Mockito.when;
48 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.ALIPHATIC_ELEMENT;
49 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.ALIPHATIC_ORDER;
50 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.AND;
51 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.AROMATIC_ELEMENT;
52 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.DEGREE;
53 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.DOUBLE_OR_AROMATIC;
54 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.ELEMENT;
55 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.FALSE;
56 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.FORMAL_CHARGE;
57 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.HAS_IMPLICIT_HYDROGEN;
58 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.HAS_ISOTOPE;
59 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.HAS_UNSPEC_ISOTOPE;
60 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.HEAVY_DEGREE;
61 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.HETERO_SUBSTITUENT_COUNT;
62 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.HYBRIDISATION_NUMBER;
63 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.IMPL_H_COUNT;
64 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.INSATURATION;
65 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.ISOTOPE;
66 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.IS_ALIPHATIC;
67 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.IS_AROMATIC;
68 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.IS_HETERO;
69 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.IS_IN_CHAIN;
70 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.IS_IN_RING;
71 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.NOT;
72 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.OR;
73 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.PERIODIC_GROUP;
74 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.REACTION_ROLE;
75 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.RECURSIVE;
76 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.RING_BOND_COUNT;
77 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.RING_COUNT;
78 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.RING_SIZE;
79 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.RING_SMALLEST;
80 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.SINGLE_OR_AROMATIC;
81 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.SINGLE_OR_DOUBLE;
82 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.STEREOCHEMISTRY;
83 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.TOTAL_DEGREE;
84 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.TOTAL_H_COUNT;
85 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.TRUE;
86 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.UNSATURATED;
87 import static org.openscience.cdk.isomorphism.matchers.Expr.Type.VALENCE;
88 
89 public class ExprTest {
90 
91     @Test
testT()92     public void testT() {
93         Expr  expr = new Expr(TRUE);
94         IAtom atom = mock(IAtom.class);
95         assertTrue(expr.matches(atom));
96     }
97 
98     @Test
testF()99     public void testF() {
100         Expr  expr = new Expr(FALSE);
101         IAtom atom = mock(IAtom.class);
102         assertFalse(expr.matches(atom));
103     }
104 
105     @Test
testAndTT()106     public void testAndTT() {
107         Expr  expr = new Expr(AND, new Expr(TRUE), new Expr(TRUE));
108         IAtom atom = mock(IAtom.class);
109         assertTrue(expr.matches(atom));
110     }
111 
112     @Test
testAndTF()113     public void testAndTF() {
114         Expr  expr = new Expr(AND, new Expr(TRUE), new Expr(FALSE));
115         IAtom atom = mock(IAtom.class);
116         assertFalse(expr.matches(atom));
117     }
118 
119     @Test
testAndFT()120     public void testAndFT() {
121         Expr  expr = new Expr(AND, new Expr(FALSE), new Expr(TRUE));
122         IAtom atom = mock(IAtom.class);
123         assertFalse(expr.matches(atom));
124     }
125 
126     @Test
testOrTT()127     public void testOrTT() {
128         Expr  expr = new Expr(OR, new Expr(TRUE), new Expr(TRUE));
129         IAtom atom = mock(IAtom.class);
130         assertTrue(expr.matches(atom));
131     }
132 
133     @Test
testOrTF()134     public void testOrTF() {
135         Expr  expr = new Expr(OR, new Expr(TRUE), new Expr(FALSE));
136         IAtom atom = mock(IAtom.class);
137         assertTrue(expr.matches(atom));
138     }
139 
140     @Test
testOrFT()141     public void testOrFT() {
142         Expr  expr = new Expr(OR, new Expr(FALSE), new Expr(TRUE));
143         IAtom atom = mock(IAtom.class);
144         assertTrue(expr.matches(atom));
145     }
146 
147     @Test
testOrFF()148     public void testOrFF() {
149         Expr  expr = new Expr(OR, new Expr(FALSE), new Expr(FALSE));
150         IAtom atom = mock(IAtom.class);
151         assertFalse(expr.matches(atom));
152     }
153 
154     @Test
testNotF()155     public void testNotF() {
156         Expr  expr = new Expr(NOT, new Expr(FALSE), null);
157         IAtom atom = mock(IAtom.class);
158         assertTrue(expr.matches(atom));
159     }
160 
161     @Test
testNotT()162     public void testNotT() {
163         Expr  expr = new Expr(NOT, new Expr(TRUE), null);
164         IAtom atom = mock(IAtom.class);
165         assertFalse(expr.matches(atom));
166     }
167 
168     @Test
testNotStereo()169     public void testNotStereo() {
170         Expr  expr = new Expr(NOT, new Expr(STEREOCHEMISTRY, 1), null);
171         IAtom atom = mock(IAtom.class);
172         assertTrue(expr.matches(atom));
173         assertTrue(expr.matches(atom, 2));
174         assertFalse(expr.matches(atom, 1));
175     }
176 
177     @Test
testNotStereo3()178     public void testNotStereo3() {
179         Expr  expr = new Expr(NOT, new Expr(STEREOCHEMISTRY, 1).or(new Expr(STEREOCHEMISTRY, 0)), null);
180         IAtom atom = mock(IAtom.class);
181         assertTrue(expr.matches(atom));
182         assertTrue(expr.matches(atom, 2));
183         assertFalse(expr.matches(atom, 1));
184     }
185 
186     @Test
testNotStereo4()187     public void testNotStereo4() {
188         Expr  expr = new Expr(NOT, new Expr(OR, new Expr(TRUE), new Expr(TRUE)), null);
189         IAtom atom = mock(IAtom.class);
190         assertFalse(expr.matches(atom));
191     }
192 
193     @Test
testStereoT()194     public void testStereoT() {
195         Expr  expr = new Expr(STEREOCHEMISTRY, 1);
196         IAtom atom = mock(IAtom.class);
197         assertTrue(expr.matches(atom, 1));
198     }
199 
200     @Test
testStereoF()201     public void testStereoF() {
202         Expr  expr = new Expr(STEREOCHEMISTRY, 1);
203         IAtom atom = mock(IAtom.class);
204         assertFalse(expr.matches(atom, 2));
205     }
206 
207     @Test
testIsAromatic()208     public void testIsAromatic() {
209         Expr  expr = new Expr(IS_AROMATIC);
210         IAtom atom = new Atom();
211         atom.setIsAromatic(false);
212         assertFalse(expr.matches(atom));
213         atom.setIsAromatic(true);
214         assertTrue(expr.matches(atom));
215     }
216 
217     @Test
testIsAliphaticT()218     public void testIsAliphaticT() {
219         Expr  expr = new Expr(IS_ALIPHATIC);
220         IAtom atom = new Atom();
221         atom.setIsAromatic(false);
222         assertTrue(expr.matches(atom));
223     }
224 
225     @Test
testIsAliphaticF()226     public void testIsAliphaticF() {
227         Expr  expr = new Expr(IS_ALIPHATIC);
228         IAtom atom = new Atom();
229         atom.setIsAromatic(true);
230         assertFalse(expr.matches(atom));
231     }
232 
233     @Test
testIsHetero()234     public void testIsHetero() {
235         Expr  expr = new Expr(IS_HETERO);
236         IAtom atom = mock(IAtom.class);
237         when(atom.getAtomicNumber()).thenReturn(1);
238         assertFalse(expr.matches(atom));
239         when(atom.getAtomicNumber()).thenReturn(6);
240         assertFalse(expr.matches(atom));
241         when(atom.getAtomicNumber()).thenReturn(8);
242         assertTrue(expr.matches(atom));
243     }
244 
245     @Test
testHasImplicitHydrogenT()246     public void testHasImplicitHydrogenT() {
247         Expr  expr = new Expr(HAS_IMPLICIT_HYDROGEN);
248         IAtom atom = mock(IAtom.class);
249         when(atom.getImplicitHydrogenCount()).thenReturn(1);
250         assertTrue(expr.matches(atom));
251         when(atom.getImplicitHydrogenCount()).thenReturn(2);
252         assertTrue(expr.matches(atom));
253     }
254 
255     @Test
testHasImplicitHydrogenF()256     public void testHasImplicitHydrogenF() {
257         Expr  expr = new Expr(HAS_IMPLICIT_HYDROGEN);
258         IAtom atom = mock(IAtom.class);
259         when(atom.getImplicitHydrogenCount()).thenReturn(0);
260         assertFalse(expr.matches(atom));
261     }
262 
263     @Test
testHasImplicitHydrogenNull()264     public void testHasImplicitHydrogenNull() {
265         Expr  expr = new Expr(HAS_IMPLICIT_HYDROGEN);
266         IAtom atom = mock(IAtom.class);
267         when(atom.getImplicitHydrogenCount()).thenReturn(null);
268         assertFalse(expr.matches(atom));
269     }
270 
271     @Test
testHasIsotope()272     public void testHasIsotope() {
273         Expr  expr = new Expr(HAS_ISOTOPE);
274         IAtom atom = mock(IAtom.class);
275         when(atom.getMassNumber()).thenReturn(null);
276         assertFalse(expr.matches(atom));
277         when(atom.getMassNumber()).thenReturn(12);
278         assertTrue(expr.matches(atom));
279     }
280 
281     @Test
testHasUnspecIsotope()282     public void testHasUnspecIsotope() {
283         Expr  expr = new Expr(HAS_UNSPEC_ISOTOPE);
284         IAtom atom = mock(IAtom.class);
285         when(atom.getMassNumber()).thenReturn(12);
286         assertFalse(expr.matches(atom));
287         when(atom.getMassNumber()).thenReturn(null);
288         assertTrue(expr.matches(atom));
289     }
290 
291     @Test
testIsInRing()292     public void testIsInRing() {
293         Expr  expr = new Expr(IS_IN_RING);
294         IAtom atom = mock(IAtom.class);
295         when(atom.isInRing()).thenReturn(false);
296         assertFalse(expr.matches(atom));
297         when(atom.isInRing()).thenReturn(true);
298         assertTrue(expr.matches(atom));
299     }
300 
301     @Test
testIsInChain()302     public void testIsInChain() {
303         Expr  expr = new Expr(IS_IN_CHAIN);
304         IAtom atom = mock(IAtom.class);
305         when(atom.isInRing()).thenReturn(false);
306         assertTrue(expr.matches(atom));
307         when(atom.isInRing()).thenReturn(true);
308         assertFalse(expr.matches(atom));
309     }
310 
311     @Test
testUnsaturatedT()312     public void testUnsaturatedT() {
313         Expr  expr = new Expr(UNSATURATED);
314         IAtom atom = mock(IAtom.class);
315         IBond bond = mock(IBond.class);
316         when(bond.getOrder()).thenReturn(IBond.Order.DOUBLE);
317         when(atom.bonds()).thenReturn(Collections.singletonList(bond));
318         assertTrue(expr.matches(atom));
319     }
320 
321     @Test
testUnsaturatedF()322     public void testUnsaturatedF() {
323         Expr  expr = new Expr(UNSATURATED);
324         IAtom atom = mock(IAtom.class);
325         IBond bond = mock(IBond.class);
326         when(bond.getOrder()).thenReturn(IBond.Order.SINGLE);
327         when(atom.bonds()).thenReturn(Collections.singletonList(bond));
328         assertFalse(expr.matches(atom));
329     }
330 
331     @Test
testElementT()332     public void testElementT() {
333         for (int num = 1; num < 54; ++num) {
334             Expr  expr = new Expr(ELEMENT, num);
335             IAtom atom = mock(IAtom.class);
336             when(atom.getAtomicNumber()).thenReturn(num);
337             assertTrue(expr.matches(atom));
338         }
339     }
340 
341     @Test
testElementF()342     public void testElementF() {
343         for (int num = 1; num < 54; ++num) {
344             Expr  expr = new Expr(ELEMENT, num);
345             IAtom atom = mock(IAtom.class);
346             when(atom.getAtomicNumber()).thenReturn(num + 1);
347             assertFalse(expr.matches(atom));
348         }
349     }
350 
351     @Test
testAliphaticElementT()352     public void testAliphaticElementT() {
353         for (int num = 1; num < 54; ++num) {
354             Expr  expr = new Expr(ALIPHATIC_ELEMENT, num);
355             IAtom atom = mock(IAtom.class);
356             when(atom.getAtomicNumber()).thenReturn(num);
357             when(atom.isAromatic()).thenReturn(false);
358             assertTrue(expr.matches(atom));
359         }
360     }
361 
362     @Test
testAliphaticElementF()363     public void testAliphaticElementF() {
364         for (int num = 1; num < 54; ++num) {
365             Expr  expr = new Expr(ALIPHATIC_ELEMENT, num);
366             IAtom atom = mock(IAtom.class);
367             when(atom.getAtomicNumber()).thenReturn(num);
368             when(atom.isAromatic()).thenReturn(true);
369             assertFalse(expr.matches(atom));
370         }
371     }
372 
373     @Test
testAliphaticElementFalse2()374     public void testAliphaticElementFalse2() {
375         for (int num = 1; num < 54; ++num) {
376             Expr  expr = new Expr(ALIPHATIC_ELEMENT, num);
377             IAtom atom = mock(IAtom.class);
378             when(atom.getAtomicNumber()).thenReturn(num + 1);
379             when(atom.isAromatic()).thenReturn(false);
380             assertFalse(expr.matches(atom));
381         }
382     }
383 
384     @Test
testAromaticElementT()385     public void testAromaticElementT() {
386         for (int num = 1; num < 54; ++num) {
387             Expr  expr = new Expr(AROMATIC_ELEMENT, num);
388             IAtom atom = mock(IAtom.class);
389             when(atom.getAtomicNumber()).thenReturn(num);
390             when(atom.isAromatic()).thenReturn(true);
391             assertTrue(expr.matches(atom));
392         }
393     }
394 
395     @Test
testAromaticElementF()396     public void testAromaticElementF() {
397         for (int num = 1; num < 54; ++num) {
398             Expr  expr = new Expr(AROMATIC_ELEMENT, num);
399             IAtom atom = mock(IAtom.class);
400             when(atom.getAtomicNumber()).thenReturn(num);
401             when(atom.isAromatic()).thenReturn(false);
402             assertFalse(expr.matches(atom));
403         }
404     }
405 
406     @Test
testAromaticElementFalse2()407     public void testAromaticElementFalse2() {
408         for (int num = 1; num < 54; ++num) {
409             Expr  expr = new Expr(AROMATIC_ELEMENT, num);
410             IAtom atom = mock(IAtom.class);
411             when(atom.getAtomicNumber()).thenReturn(num + 1);
412             when(atom.isAromatic()).thenReturn(true);
413             assertFalse(expr.matches(atom));
414         }
415     }
416 
417     @Test
testHCountT()418     public void testHCountT() {
419         Expr  expr = new Expr(IMPL_H_COUNT, 1);
420         IAtom atom = mock(IAtom.class);
421         when(atom.getImplicitHydrogenCount()).thenReturn(1);
422         assertTrue(expr.matches(atom));
423     }
424 
425     @Test
testHCountF()426     public void testHCountF() {
427         Expr  expr = new Expr(IMPL_H_COUNT, 2);
428         IAtom atom = mock(IAtom.class);
429         when(atom.getImplicitHydrogenCount()).thenReturn(1);
430         assertFalse(expr.matches(atom));
431     }
432 
433     @Test
testTotalHCountT()434     public void testTotalHCountT() {
435         Expr  expr = new Expr(TOTAL_H_COUNT, 3);
436         IAtom atom = mock(IAtom.class);
437         IAtom h    = mock(IAtom.class);
438         IBond b    = mock(IBond.class);
439         when(b.getOther(atom)).thenReturn(h);
440         when(b.getOther(h)).thenReturn(atom);
441         when(atom.getImplicitHydrogenCount()).thenReturn(2);
442         when(h.getAtomicNumber()).thenReturn(1);
443         when(atom.bonds()).thenReturn(Collections.singletonList(b));
444         assertTrue(expr.matches(atom));
445     }
446 
447     @Test
testTotalHCountF()448     public void testTotalHCountF() {
449         Expr  expr = new Expr(TOTAL_H_COUNT, 2);
450         IAtom atom = mock(IAtom.class);
451         IAtom h    = mock(IAtom.class);
452         IBond b    = mock(IBond.class);
453         when(b.getOther(atom)).thenReturn(h);
454         when(b.getOther(h)).thenReturn(atom);
455         when(atom.getImplicitHydrogenCount()).thenReturn(2);
456         when(h.getAtomicNumber()).thenReturn(1);
457         when(atom.bonds()).thenReturn(Collections.singletonList(b));
458         assertFalse(expr.matches(atom));
459     }
460 
461     @Test
testTotalHCountNullImplT()462     public void testTotalHCountNullImplT() {
463         Expr  expr = new Expr(TOTAL_H_COUNT, 1);
464         IAtom atom = mock(IAtom.class);
465         IAtom h    = mock(IAtom.class);
466         IBond b    = mock(IBond.class);
467         when(b.getOther(atom)).thenReturn(h);
468         when(b.getOther(h)).thenReturn(atom);
469         when(atom.getImplicitHydrogenCount()).thenReturn(null);
470         when(h.getAtomicNumber()).thenReturn(1);
471         when(atom.bonds()).thenReturn(Collections.singletonList(b));
472         assertTrue(expr.matches(atom));
473     }
474 
475     @Test
testTotalHCountImplF()476     public void testTotalHCountImplF() {
477         Expr  expr = new Expr(TOTAL_H_COUNT, 1);
478         IAtom atom = mock(IAtom.class);
479         IAtom h    = mock(IAtom.class);
480         IBond b    = mock(IBond.class);
481         when(b.getOther(atom)).thenReturn(h);
482         when(b.getOther(h)).thenReturn(atom);
483         when(atom.getImplicitHydrogenCount()).thenReturn(2);
484         when(h.getAtomicNumber()).thenReturn(1);
485         when(atom.bonds()).thenReturn(Collections.singletonList(b));
486         assertFalse(expr.matches(atom));
487     }
488 
489     @Test
testDegreeT()490     public void testDegreeT() {
491         Expr  expr = new Expr(DEGREE, 1);
492         IAtom atom = mock(IAtom.class);
493         when(atom.getBondCount()).thenReturn(1);
494         assertTrue(expr.matches(atom));
495     }
496 
497     @Test
testDegreeF()498     public void testDegreeF() {
499         Expr  expr = new Expr(DEGREE, 2);
500         IAtom atom = mock(IAtom.class);
501         when(atom.getBondCount()).thenReturn(1);
502         assertFalse(expr.matches(atom));
503     }
504 
505     @Test
testTotalDegreeT()506     public void testTotalDegreeT() {
507         Expr  expr = new Expr(TOTAL_DEGREE, 1);
508         IAtom atom = mock(IAtom.class);
509         when(atom.getBondCount()).thenReturn(1);
510         when(atom.getImplicitHydrogenCount()).thenReturn(0);
511         assertTrue(expr.matches(atom));
512     }
513 
514     @Test
testTotalDegreeF()515     public void testTotalDegreeF() {
516         Expr  expr = new Expr(TOTAL_DEGREE, 1);
517         IAtom atom = mock(IAtom.class);
518         when(atom.getBondCount()).thenReturn(1);
519         when(atom.getImplicitHydrogenCount()).thenReturn(1);
520         assertFalse(expr.matches(atom));
521     }
522 
523     @Test
testHeavyDegreeT()524     public void testHeavyDegreeT() {
525         Expr  expr = new Expr(HEAVY_DEGREE, 0);
526         IAtom atom = mock(IAtom.class);
527         IAtom h    = mock(IAtom.class);
528         IBond b    = mock(IBond.class);
529         when(atom.getBondCount()).thenReturn(1);
530         when(b.getOther(atom)).thenReturn(h);
531         when(b.getOther(h)).thenReturn(atom);
532         when(atom.getImplicitHydrogenCount()).thenReturn(2);
533         when(h.getAtomicNumber()).thenReturn(1);
534         when(atom.bonds()).thenReturn(Collections.singletonList(b));
535         assertTrue(expr.matches(atom));
536     }
537 
538     @Test
testHeavyDegreeF()539     public void testHeavyDegreeF() {
540         Expr  expr = new Expr(HEAVY_DEGREE, 1);
541         IAtom atom = mock(IAtom.class);
542         IAtom h    = mock(IAtom.class);
543         IBond b    = mock(IBond.class);
544         when(atom.getBondCount()).thenReturn(1);
545         when(b.getOther(atom)).thenReturn(h);
546         when(b.getOther(h)).thenReturn(atom);
547         when(atom.getImplicitHydrogenCount()).thenReturn(2);
548         when(h.getAtomicNumber()).thenReturn(1);
549         when(atom.bonds()).thenReturn(Collections.singletonList(b));
550         assertFalse(expr.matches(atom));
551     }
552 
553     @Test
testHeteroSubT()554     public void testHeteroSubT() {
555         Expr  expr = new Expr(HETERO_SUBSTITUENT_COUNT, 1);
556         IAtom atom = mock(IAtom.class);
557         IAtom o    = mock(IAtom.class);
558         IBond b    = mock(IBond.class);
559         when(atom.getBondCount()).thenReturn(1);
560         when(b.getOther(atom)).thenReturn(o);
561         when(b.getOther(o)).thenReturn(atom);
562         when(atom.getImplicitHydrogenCount()).thenReturn(2);
563         when(o.getAtomicNumber()).thenReturn(8);
564         when(atom.bonds()).thenReturn(Collections.singletonList(b));
565         assertTrue(expr.matches(atom));
566     }
567 
568     @Test
testHeteroSubFailFastF()569     public void testHeteroSubFailFastF() {
570         Expr  expr = new Expr(HETERO_SUBSTITUENT_COUNT, 2);
571         IAtom atom = mock(IAtom.class);
572         IAtom o    = mock(IAtom.class);
573         IBond b    = mock(IBond.class);
574         when(atom.getBondCount()).thenReturn(1);
575         when(b.getOther(atom)).thenReturn(o);
576         when(b.getOther(o)).thenReturn(atom);
577         when(atom.getImplicitHydrogenCount()).thenReturn(2);
578         when(o.getAtomicNumber()).thenReturn(8);
579         when(atom.bonds()).thenReturn(Collections.singletonList(b));
580         assertFalse(expr.matches(atom));
581     }
582 
583     @Test
testHeteroSubF()584     public void testHeteroSubF() {
585         Expr  expr = new Expr(HETERO_SUBSTITUENT_COUNT, 1);
586         IAtom atom = mock(IAtom.class);
587         IAtom c    = mock(IAtom.class);
588         IBond b    = mock(IBond.class);
589         when(atom.getBondCount()).thenReturn(1);
590         when(b.getOther(atom)).thenReturn(c);
591         when(b.getOther(c)).thenReturn(atom);
592         when(atom.getImplicitHydrogenCount()).thenReturn(2);
593         when(c.getAtomicNumber()).thenReturn(6);
594         when(atom.bonds()).thenReturn(Collections.singletonList(b));
595         assertFalse(expr.matches(atom));
596     }
597 
598     @Test
testValenceT()599     public void testValenceT() {
600         Expr  expr = new Expr(VALENCE, 4);
601         IAtom a1   = mock(IAtom.class);
602         IBond b1   = mock(IBond.class);
603         IBond b2   = mock(IBond.class);
604         when(a1.getImplicitHydrogenCount()).thenReturn(1);
605         when(b1.getOrder()).thenReturn(IBond.Order.DOUBLE);
606         when(b2.getOrder()).thenReturn(IBond.Order.SINGLE);
607         when(a1.bonds()).thenReturn(Arrays.asList(b1, b2));
608         assertTrue(expr.matches(a1));
609     }
610 
611     @Test
testValenceF()612     public void testValenceF() {
613         Expr  expr = new Expr(VALENCE, 4);
614         IAtom a1   = mock(IAtom.class);
615         IBond b1   = mock(IBond.class);
616         IBond b2   = mock(IBond.class);
617         when(a1.getImplicitHydrogenCount()).thenReturn(1);
618         when(b1.getOrder()).thenReturn(IBond.Order.SINGLE);
619         when(b2.getOrder()).thenReturn(IBond.Order.SINGLE);
620         when(a1.bonds()).thenReturn(Arrays.asList(b1, b2));
621         assertFalse(expr.matches(a1));
622     }
623 
624     @Test
testValenceNullOrderT()625     public void testValenceNullOrderT() {
626         Expr  expr = new Expr(VALENCE, 4);
627         IAtom a1   = mock(IAtom.class);
628         IBond b1   = mock(IBond.class);
629         IBond b2   = mock(IBond.class);
630         when(a1.getImplicitHydrogenCount()).thenReturn(1);
631         when(b1.getOrder()).thenReturn(IBond.Order.DOUBLE);
632         when(b2.getOrder()).thenReturn(null);
633         when(a1.bonds()).thenReturn(Arrays.asList(b1, b2));
634         assertFalse(expr.matches(a1));
635     }
636 
637     @Test
testValenceFailFastF()638     public void testValenceFailFastF() {
639         Expr  expr = new Expr(VALENCE, 2);
640         IAtom a1   = mock(IAtom.class);
641         when(a1.getImplicitHydrogenCount()).thenReturn(4);
642         assertFalse(expr.matches(a1));
643     }
644 
645     @Test
testIsotopeT()646     public void testIsotopeT() {
647         Expr  expr = new Expr(ISOTOPE, 13);
648         IAtom atom = mock(IAtom.class);
649         when(atom.getMassNumber()).thenReturn(13);
650         assertTrue(expr.matches(atom));
651     }
652 
653     @Test
testIsotopeF()654     public void testIsotopeF() {
655         Expr  expr = new Expr(ISOTOPE, 12);
656         IAtom atom = mock(IAtom.class);
657         when(atom.getMassNumber()).thenReturn(13);
658         assertFalse(expr.matches(atom));
659     }
660 
661     @Test
testFormalChargeT()662     public void testFormalChargeT() {
663         Expr  expr = new Expr(FORMAL_CHARGE, -1);
664         IAtom atom = mock(IAtom.class);
665         when(atom.getFormalCharge()).thenReturn(-1);
666         assertTrue(expr.matches(atom));
667     }
668 
669     @Test
testFormalChargeF()670     public void testFormalChargeF() {
671         Expr  expr = new Expr(FORMAL_CHARGE, -1);
672         IAtom atom = mock(IAtom.class);
673         when(atom.getFormalCharge()).thenReturn(0);
674         assertFalse(expr.matches(atom));
675     }
676 
677     @Test
testRingBondCountT()678     public void testRingBondCountT() {
679         Expr  expr = new Expr(RING_BOND_COUNT, 3);
680         IAtom atom = mock(IAtom.class);
681         IBond b1   = mock(IBond.class);
682         IBond b2   = mock(IBond.class);
683         IBond b3   = mock(IBond.class);
684         when(atom.isInRing()).thenReturn(true);
685         when(atom.getBondCount()).thenReturn(3);
686         when(b1.isInRing()).thenReturn(true);
687         when(b2.isInRing()).thenReturn(true);
688         when(b3.isInRing()).thenReturn(true);
689         when(atom.bonds()).thenReturn(Arrays.asList(b1, b2, b3));
690         assertTrue(expr.matches(atom));
691     }
692 
693     @Test
testRingBondCountF()694     public void testRingBondCountF() {
695         Expr  expr = new Expr(RING_BOND_COUNT, 3);
696         IAtom atom = mock(IAtom.class);
697         IBond b1   = mock(IBond.class);
698         IBond b2   = mock(IBond.class);
699         IBond b3   = mock(IBond.class);
700         when(atom.isInRing()).thenReturn(true);
701         when(atom.getBondCount()).thenReturn(3);
702         when(b1.isInRing()).thenReturn(true);
703         when(b2.isInRing()).thenReturn(true);
704         when(b3.isInRing()).thenReturn(false);
705         when(atom.bonds()).thenReturn(Arrays.asList(b1, b2, b3));
706         assertFalse(expr.matches(atom));
707     }
708 
709     @Test
testRingBondCountNonRingF()710     public void testRingBondCountNonRingF() {
711         Expr  expr = new Expr(RING_BOND_COUNT, 3);
712         IAtom atom = mock(IAtom.class);
713         when(atom.isInRing()).thenReturn(false);
714         assertFalse(expr.matches(atom));
715     }
716 
717     @Test
testRingBondCountLessBondsF()718     public void testRingBondCountLessBondsF() {
719         Expr  expr = new Expr(RING_BOND_COUNT, 3);
720         IAtom atom = mock(IAtom.class);
721         when(atom.isInRing()).thenReturn(true);
722         when(atom.getBondCount()).thenReturn(2);
723         assertFalse(expr.matches(atom));
724     }
725 
726     @Test
testInsaturationT()727     public void testInsaturationT() {
728         Expr  expr = new Expr(INSATURATION, 2);
729         IAtom atom = mock(IAtom.class);
730         IBond b1   = mock(IBond.class);
731         IBond b2   = mock(IBond.class);
732         when(b1.getOrder()).thenReturn(IBond.Order.DOUBLE);
733         when(b2.getOrder()).thenReturn(IBond.Order.DOUBLE);
734         when(atom.bonds()).thenReturn(Arrays.asList(b1, b2));
735         assertTrue(expr.matches(atom));
736     }
737 
738     @Test
testInsaturationF()739     public void testInsaturationF() {
740         Expr  expr = new Expr(INSATURATION, 2);
741         IAtom atom = mock(IAtom.class);
742         IBond b1   = mock(IBond.class);
743         IBond b2   = mock(IBond.class);
744         when(b1.getOrder()).thenReturn(IBond.Order.SINGLE);
745         when(b2.getOrder()).thenReturn(IBond.Order.DOUBLE);
746         when(atom.bonds()).thenReturn(Arrays.asList(b1, b2));
747         assertFalse(expr.matches(atom));
748     }
749 
750     @Test
testGroupT()751     public void testGroupT() {
752         Expr expr = new Expr(PERIODIC_GROUP,
753                              Elements.Chlorine.group());
754         IAtom atom = mock(IAtom.class);
755         when(atom.getAtomicNumber()).thenReturn(9);
756         assertTrue(expr.matches(atom));
757         when(atom.getAtomicNumber()).thenReturn(17);
758         assertTrue(expr.matches(atom));
759         when(atom.getAtomicNumber()).thenReturn(35);
760         assertTrue(expr.matches(atom));
761         when(atom.getAtomicNumber()).thenReturn(53);
762         assertTrue(expr.matches(atom));
763     }
764 
765     @Test
testGroupF()766     public void testGroupF() {
767         Expr expr = new Expr(PERIODIC_GROUP,
768                              Elements.Chlorine.group());
769         IAtom atom = mock(IAtom.class);
770         when(atom.getAtomicNumber()).thenReturn(8);
771         assertFalse(expr.matches(atom));
772         when(atom.getAtomicNumber()).thenReturn(16);
773         assertFalse(expr.matches(atom));
774         when(atom.getAtomicNumber()).thenReturn(34);
775         assertFalse(expr.matches(atom));
776         when(atom.getAtomicNumber()).thenReturn(52);
777         assertFalse(expr.matches(atom));
778     }
779 
780     @Test
testGroupNull()781     public void testGroupNull() {
782         Expr expr = new Expr(PERIODIC_GROUP,
783                              Elements.Chlorine.group());
784         IAtom atom = mock(IAtom.class);
785         when(atom.getAtomicNumber()).thenReturn(null);
786         assertFalse(expr.matches(atom));
787     }
788 
789     @Test
testHybridisation0F()790     public void testHybridisation0F() {
791         Expr expr = new Expr(HYBRIDISATION_NUMBER,
792                              0);
793         IAtom atom = mock(IAtom.class);
794         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP1);
795         assertFalse(expr.matches(atom));
796     }
797 
798     @Test
testHybridisationSp1T()799     public void testHybridisationSp1T() {
800         Expr expr = new Expr(HYBRIDISATION_NUMBER,
801                              1);
802         IAtom atom = mock(IAtom.class);
803         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP1);
804         assertTrue(expr.matches(atom));
805     }
806 
807     @Test
testHybridisationSp1F()808     public void testHybridisationSp1F() {
809         Expr expr = new Expr(HYBRIDISATION_NUMBER,
810                              1);
811         IAtom atom = mock(IAtom.class);
812         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP2);
813         assertFalse(expr.matches(atom));
814     }
815 
816     @Test
testHybridisationSp2T()817     public void testHybridisationSp2T() {
818         Expr expr = new Expr(HYBRIDISATION_NUMBER,
819                              2);
820         IAtom atom = mock(IAtom.class);
821         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP2);
822         assertTrue(expr.matches(atom));
823     }
824 
825     @Test
testHybridisationSp2F()826     public void testHybridisationSp2F() {
827         Expr expr = new Expr(HYBRIDISATION_NUMBER,
828                              2);
829         IAtom atom = mock(IAtom.class);
830         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP1);
831         assertFalse(expr.matches(atom));
832     }
833 
834     @Test
testHybridisationSp3T()835     public void testHybridisationSp3T() {
836         Expr expr = new Expr(HYBRIDISATION_NUMBER,
837                              3);
838         IAtom atom = mock(IAtom.class);
839         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP3);
840         assertTrue(expr.matches(atom));
841     }
842 
843     @Test
testHybridisationSp3F()844     public void testHybridisationSp3F() {
845         Expr expr = new Expr(HYBRIDISATION_NUMBER,
846                              3);
847         IAtom atom = mock(IAtom.class);
848         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP1);
849         assertFalse(expr.matches(atom));
850     }
851 
852     @Test
testHybridisationSp3d1T()853     public void testHybridisationSp3d1T() {
854         Expr expr = new Expr(HYBRIDISATION_NUMBER,
855                              4);
856         IAtom atom = mock(IAtom.class);
857         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP3D1);
858         assertTrue(expr.matches(atom));
859     }
860 
861     @Test
testHybridisationSp3d1F()862     public void testHybridisationSp3d1F() {
863         Expr expr = new Expr(HYBRIDISATION_NUMBER,
864                              4);
865         IAtom atom = mock(IAtom.class);
866         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP1);
867         assertFalse(expr.matches(atom));
868     }
869 
870     @Test
testHybridisationSp3d2T()871     public void testHybridisationSp3d2T() {
872         Expr expr = new Expr(HYBRIDISATION_NUMBER,
873                              5);
874         IAtom atom = mock(IAtom.class);
875         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP3D2);
876         assertTrue(expr.matches(atom));
877     }
878 
879     @Test
testHybridisationSp3d2F()880     public void testHybridisationSp3d2F() {
881         Expr expr = new Expr(HYBRIDISATION_NUMBER,
882                              5);
883         IAtom atom = mock(IAtom.class);
884         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP1);
885         assertFalse(expr.matches(atom));
886     }
887 
888     @Test
testHybridisationSp3d3T()889     public void testHybridisationSp3d3T() {
890         Expr expr = new Expr(HYBRIDISATION_NUMBER,
891                              6);
892         IAtom atom = mock(IAtom.class);
893         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP3D3);
894         assertTrue(expr.matches(atom));
895     }
896 
897     @Test
testHybridisationSp3d3F()898     public void testHybridisationSp3d3F() {
899         Expr expr = new Expr(HYBRIDISATION_NUMBER,
900                              6);
901         IAtom atom = mock(IAtom.class);
902         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP1);
903         assertFalse(expr.matches(atom));
904     }
905 
906     @Test
testHybridisationSp3d4T()907     public void testHybridisationSp3d4T() {
908         Expr expr = new Expr(HYBRIDISATION_NUMBER,
909                              7);
910         IAtom atom = mock(IAtom.class);
911         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP3D4);
912         assertTrue(expr.matches(atom));
913     }
914 
915     @Test
testHybridisationSp3d4F()916     public void testHybridisationSp3d4F() {
917         Expr expr = new Expr(HYBRIDISATION_NUMBER,
918                              7);
919         IAtom atom = mock(IAtom.class);
920         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP1);
921         assertFalse(expr.matches(atom));
922     }
923 
924     @Test
testHybridisationSp3d5T()925     public void testHybridisationSp3d5T() {
926         Expr expr = new Expr(HYBRIDISATION_NUMBER,
927                              8);
928         IAtom atom = mock(IAtom.class);
929         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP3D5);
930         assertTrue(expr.matches(atom));
931     }
932 
933     @Test
testHybridisationSp1Null()934     public void testHybridisationSp1Null() {
935         Expr expr = new Expr(HYBRIDISATION_NUMBER,
936                              1);
937         IAtom atom = mock(IAtom.class);
938         when(atom.getHybridization()).thenReturn(null);
939         assertFalse(expr.matches(atom));
940     }
941 
942     @Test
testHybridisationSp3d5F()943     public void testHybridisationSp3d5F() {
944         Expr expr = new Expr(HYBRIDISATION_NUMBER,
945                              8);
946         IAtom atom = mock(IAtom.class);
947         when(atom.getHybridization()).thenReturn(IAtomType.Hybridization.SP1);
948         assertFalse(expr.matches(atom));
949     }
950 
951     @Test
testReactionRoleT()952     public void testReactionRoleT() {
953         Expr expr = new Expr(REACTION_ROLE,
954                              ReactionRole.Reactant.ordinal());
955         IAtom atom = mock(IAtom.class);
956         when(atom.getProperty(CDKConstants.REACTION_ROLE)).thenReturn(ReactionRole.Reactant);
957         assertTrue(expr.matches(atom));
958     }
959 
960     @Test
testReactionRoleF()961     public void testReactionRoleF() {
962         Expr expr = new Expr(REACTION_ROLE,
963                              ReactionRole.Reactant.ordinal());
964         IAtom atom = mock(IAtom.class);
965         when(atom.getProperty(CDKConstants.REACTION_ROLE)).thenReturn(ReactionRole.Product);
966         assertFalse(expr.matches(atom));
967     }
968 
969     @Test
testReactionRoleNull()970     public void testReactionRoleNull() {
971         Expr expr = new Expr(REACTION_ROLE,
972                              ReactionRole.Reactant.ordinal());
973         IAtom atom = mock(IAtom.class);
974         when(atom.getProperty(CDKConstants.REACTION_ROLE)).thenReturn(null);
975         assertFalse(expr.matches(atom));
976     }
977 
978     @Test
testRingSize6()979     public void testRingSize6() {
980         Expr           expr = new Expr(RING_SIZE, 6);
981         IAtomContainer mol  = TestMoleculeFactory.makeNaphthalene();
982         Cycles.markRingAtomsAndBonds(mol);
983         assertTrue(expr.matches(mol.getAtom(0)));
984     }
985 
986     @Test
testRingSize10()987     public void testRingSize10() {
988         Expr           expr = new Expr(RING_SIZE, 10);
989         IAtomContainer mol  = TestMoleculeFactory.makeNaphthalene();
990         Cycles.markRingAtomsAndBonds(mol);
991         assertTrue(expr.matches(mol.getAtom(0)));
992     }
993 
994     @Test
testRingSmallestNonRing()995     public void testRingSmallestNonRing() {
996         Expr  expr = new Expr(RING_SMALLEST, 6);
997         IAtom atom = mock(IAtom.class);
998         when(atom.isInRing()).thenReturn(false);
999         assertFalse(expr.matches(atom));
1000     }
1001 
1002     @Test
testRingNonRing()1003     public void testRingNonRing() {
1004         Expr  expr = new Expr(RING_SIZE, 6);
1005         IAtom atom = mock(IAtom.class);
1006         when(atom.isInRing()).thenReturn(false);
1007         assertFalse(expr.matches(atom));
1008     }
1009 
1010     @Test
testRingCountNonRing()1011     public void testRingCountNonRing() {
1012         Expr  expr = new Expr(RING_COUNT, 6);
1013         IAtom atom = mock(IAtom.class);
1014         when(atom.isInRing()).thenReturn(false);
1015         assertFalse(expr.matches(atom));
1016     }
1017 
1018     @Test
testRingSmallestSize6()1019     public void testRingSmallestSize6() {
1020         Expr           expr = new Expr(RING_SMALLEST, 6);
1021         IAtomContainer mol  = TestMoleculeFactory.makeNaphthalene();
1022         Cycles.markRingAtomsAndBonds(mol);
1023         assertTrue(expr.matches(mol.getAtom(0)));
1024     }
1025 
1026     @Test
testRingSmallestSize10()1027     public void testRingSmallestSize10() {
1028         Expr           expr = new Expr(RING_SMALLEST, 10);
1029         IAtomContainer mol  = TestMoleculeFactory.makeNaphthalene();
1030         Cycles.markRingAtomsAndBonds(mol);
1031         assertFalse(expr.matches(mol.getAtom(0)));
1032     }
1033 
1034     @Test
testRingSmallestSize5And6()1035     public void testRingSmallestSize5And6() {
1036         Expr           expr5 = new Expr(RING_SMALLEST, 5);
1037         Expr           expr6 = new Expr(RING_SMALLEST, 6);
1038         IAtomContainer mol   = TestMoleculeFactory.makeIndole();
1039         Cycles.markRingAtomsAndBonds(mol);
1040         int numSmall5 = 0;
1041         int numSmall6 = 0;
1042         for (IAtom atom : mol.atoms()) {
1043             if (expr5.matches(atom))
1044                 numSmall5++;
1045             if (expr6.matches(atom))
1046                 numSmall6++;
1047         }
1048         assertThat(numSmall5, is(5));
1049         assertThat(numSmall6, is(4));
1050     }
1051 
1052     @Test
testRingSize5And6()1053     public void testRingSize5And6() {
1054         Expr           expr5 = new Expr(RING_SIZE, 5);
1055         Expr           expr6 = new Expr(RING_SIZE, 6);
1056         IAtomContainer mol   = TestMoleculeFactory.makeIndole();
1057         Cycles.markRingAtomsAndBonds(mol);
1058         int numSmall5 = 0;
1059         int numSmall6 = 0;
1060         for (IAtom atom : mol.atoms()) {
1061             if (expr5.matches(atom))
1062                 numSmall5++;
1063             if (expr6.matches(atom))
1064                 numSmall6++;
1065         }
1066         assertThat(numSmall5, is(5));
1067         assertThat(numSmall6, is(6));
1068     }
1069 
1070     @Test
testRingCount2()1071     public void testRingCount2() {
1072         Expr           expr = new Expr(RING_COUNT, 2);
1073         IAtomContainer mol  = TestMoleculeFactory.makeNaphthalene();
1074         Cycles.markRingAtomsAndBonds(mol);
1075         int count = 0;
1076         for (IAtom atom : mol.atoms()) {
1077             if (expr.matches(atom))
1078                 count++;
1079         }
1080         assertThat(count, is(2));
1081     }
1082 
1083     @Test(expected = IllegalArgumentException.class)
nonAtomExpr()1084     public void nonAtomExpr() {
1085         Expr  expr = new Expr(ALIPHATIC_ORDER, 2);
1086         IAtom atom = mock(IAtom.class);
1087         assertFalse(expr.matches(atom));
1088     }
1089 
1090 //    @Ignore("to be added back in later")
1091 //    public void testRecursiveT() {
1092 //        IAtomContainer subexpr = new QueryAtomContainer(null);
1093 //        QueryAtom      qatom   = new QueryAtom(null);
1094 //        qatom.setExpression(new Expr(TRUE));
1095 //        subexpr.addAtom(qatom);
1096 //        Expr           expr = new Expr(RECURSIVE, subexpr);
1097 //        IAtomContainer mol  = TestMoleculeFactory.makeNaphthalene();
1098 //        assertTrue(expr.matches(mol.getAtom(0)));
1099 //    }
1100 //
1101 //    @Ignore("to be added back in later")
1102 //    public void testRecursiveF() {
1103 //        IAtomContainer subexpr = new QueryAtomContainer(null);
1104 //        QueryAtom      qatom   = new QueryAtom(null);
1105 //        qatom.setExpression(new Expr(FALSE));
1106 //        subexpr.addAtom(qatom);
1107 //        Expr           expr = new Expr(RECURSIVE, subexpr);
1108 //        IAtomContainer mol  = TestMoleculeFactory.makeNaphthalene();
1109 //        assertFalse(expr.matches(mol.getAtom(0)));
1110 //    }
1111 //
1112 //    @Ignore("to be added back in later")
1113 //    public void testRecursiveF2() {
1114 //        IAtomContainer subexpr = new QueryAtomContainer(null);
1115 //        QueryAtom      qatom   = new QueryAtom(null);
1116 //        qatom.setExpression(new Expr(ELEMENT, 8));
1117 //        subexpr.addAtom(qatom);
1118 //        Expr           expr = new Expr(RECURSIVE, subexpr);
1119 //        IAtomContainer mol  = TestMoleculeFactory.makeNaphthalene();
1120 //        IAtom          atom = mol.getBuilder().newAtom();
1121 //        atom.setAtomicNumber(8);
1122 //        mol.addAtom(atom);
1123 //        assertFalse(expr.matches(mol.getAtom(0)));
1124 //        assertTrue(expr.matches(mol.getAtom(mol.getAtomCount() - 1)));
1125 //    }
1126 
1127     /* Bond Exprs */
1128 
1129     @Test
testBondT()1130     public void testBondT() {
1131         Expr  expr = new Expr(TRUE);
1132         IBond bond = mock(IBond.class);
1133         assertTrue(expr.matches(bond));
1134     }
1135 
1136     @Test
testBondF()1137     public void testBondF() {
1138         Expr  expr = new Expr(FALSE);
1139         IBond bond = mock(IBond.class);
1140         assertFalse(expr.matches(bond));
1141     }
1142 
1143     @Test
testBondAndTT()1144     public void testBondAndTT() {
1145         Expr  expr = new Expr(AND, new Expr(TRUE), new Expr(TRUE));
1146         IBond bond = mock(IBond.class);
1147         assertTrue(expr.matches(bond));
1148     }
1149 
1150     @Test
testBondAndTF()1151     public void testBondAndTF() {
1152         Expr  expr = new Expr(AND, new Expr(TRUE), new Expr(FALSE));
1153         IBond bond = mock(IBond.class);
1154         assertFalse(expr.matches(bond));
1155     }
1156 
1157     @Test
testBondAndFT()1158     public void testBondAndFT() {
1159         Expr  expr = new Expr(AND, new Expr(FALSE), new Expr(TRUE));
1160         IBond bond = mock(IBond.class);
1161         assertFalse(expr.matches(bond));
1162     }
1163 
1164     @Test
testBondOrTT()1165     public void testBondOrTT() {
1166         Expr  expr = new Expr(OR, new Expr(TRUE), new Expr(TRUE));
1167         IBond bond = mock(IBond.class);
1168         assertTrue(expr.matches(bond));
1169     }
1170 
1171     @Test
testBondOrTF()1172     public void testBondOrTF() {
1173         Expr  expr = new Expr(OR, new Expr(TRUE), new Expr(FALSE));
1174         IBond bond = mock(IBond.class);
1175         assertTrue(expr.matches(bond));
1176     }
1177 
1178     @Test
testBondOrFT()1179     public void testBondOrFT() {
1180         Expr  expr = new Expr(OR, new Expr(FALSE), new Expr(TRUE));
1181         IBond bond = mock(IBond.class);
1182         assertTrue(expr.matches(bond));
1183     }
1184 
1185     @Test
testBondOrFF()1186     public void testBondOrFF() {
1187         Expr  expr = new Expr(OR, new Expr(FALSE), new Expr(FALSE));
1188         IBond bond = mock(IBond.class);
1189         assertFalse(expr.matches(bond));
1190     }
1191 
1192     @Test
testBondNotF()1193     public void testBondNotF() {
1194         Expr  expr = new Expr(NOT, new Expr(FALSE), null);
1195         IBond bond = mock(IBond.class);
1196         assertTrue(expr.matches(bond));
1197     }
1198 
1199     @Test
testBondNotT()1200     public void testBondNotT() {
1201         Expr  expr = new Expr(NOT, new Expr(TRUE), null);
1202         IBond bond = mock(IBond.class);
1203         assertFalse(expr.matches(bond));
1204     }
1205 
1206     @Test
testBondNotStereo()1207     public void testBondNotStereo() {
1208         Expr  expr = new Expr(NOT, new Expr(STEREOCHEMISTRY, 1), null);
1209         IBond bond = mock(IBond.class);
1210         assertTrue(expr.matches(bond));
1211         assertTrue(expr.matches(bond, 2));
1212         assertFalse(expr.matches(bond, 1));
1213     }
1214 
1215     @Test
testBondNotStereo3()1216     public void testBondNotStereo3() {
1217         Expr  expr = new Expr(NOT, new Expr(STEREOCHEMISTRY, 1).or(new Expr(STEREOCHEMISTRY, 0)), null);
1218         IBond bond = mock(IBond.class);
1219         assertTrue(expr.matches(bond));
1220         assertTrue(expr.matches(bond, 2));
1221         assertFalse(expr.matches(bond, 1));
1222     }
1223 
1224     @Test
testBondNotStereo4()1225     public void testBondNotStereo4() {
1226         Expr  expr = new Expr(NOT, new Expr(OR, new Expr(TRUE), new Expr(TRUE)), null);
1227         IBond bond = mock(IBond.class);
1228         assertFalse(expr.matches(bond));
1229     }
1230 
1231     @Test
testBondStereoT()1232     public void testBondStereoT() {
1233         Expr  expr = new Expr(STEREOCHEMISTRY, 1);
1234         IBond bond = mock(IBond.class);
1235         assertTrue(expr.matches(bond, 1));
1236     }
1237 
1238     @Test
testBondStereoF()1239     public void testBondStereoF() {
1240         Expr  expr = new Expr(STEREOCHEMISTRY, 1);
1241         IBond bond = mock(IBond.class);
1242         assertFalse(expr.matches(bond, 2));
1243     }
1244 
1245     @Test
testBondIsAromaticT()1246     public void testBondIsAromaticT() {
1247         Expr  expr = new Expr(IS_AROMATIC);
1248         IBond bond = mock(IBond.class);
1249         when(bond.isAromatic()).thenReturn(true);
1250         assertTrue(expr.matches(bond));
1251     }
1252 
1253     @Test
testBondIsAromaticF()1254     public void testBondIsAromaticF() {
1255         Expr  expr = new Expr(IS_AROMATIC);
1256         IBond bond = mock(IBond.class);
1257         when(bond.isAromatic()).thenReturn(false);
1258         assertFalse(expr.matches(bond));
1259     }
1260 
1261     @Test
testBondIsAliphaticT()1262     public void testBondIsAliphaticT() {
1263         Expr  expr = new Expr(IS_ALIPHATIC);
1264         IBond bond = mock(IBond.class);
1265         when(bond.isAromatic()).thenReturn(false);
1266         assertTrue(expr.matches(bond));
1267     }
1268 
1269     @Test
testBondIsAliphaticF()1270     public void testBondIsAliphaticF() {
1271         Expr  expr = new Expr(IS_ALIPHATIC);
1272         IBond bond = mock(IBond.class);
1273         when(bond.isAromatic()).thenReturn(true);
1274         assertFalse(expr.matches(bond));
1275     }
1276 
1277     @Test
testBondIsChainT()1278     public void testBondIsChainT() {
1279         Expr  expr = new Expr(IS_IN_CHAIN);
1280         IBond bond = mock(IBond.class);
1281         when(bond.isInRing()).thenReturn(false);
1282         assertTrue(expr.matches(bond));
1283     }
1284 
1285     @Test
testBondIsChainF()1286     public void testBondIsChainF() {
1287         Expr  expr = new Expr(IS_IN_CHAIN);
1288         IBond bond = mock(IBond.class);
1289         when(bond.isInRing()).thenReturn(true);
1290         assertFalse(expr.matches(bond));
1291     }
1292 
1293     @Test
testBondIsRingT()1294     public void testBondIsRingT() {
1295         Expr  expr = new Expr(IS_IN_RING);
1296         IBond bond = mock(IBond.class);
1297         when(bond.isInRing()).thenReturn(true);
1298         assertTrue(expr.matches(bond));
1299     }
1300 
1301     @Test
testBondIsRingF()1302     public void testBondIsRingF() {
1303         Expr  expr = new Expr(IS_IN_RING);
1304         IBond bond = mock(IBond.class);
1305         when(bond.isInRing()).thenReturn(false);
1306         assertFalse(expr.matches(bond));
1307     }
1308 
1309     @Test
testBondOrderT()1310     public void testBondOrderT() {
1311         Expr  expr = new Expr(ALIPHATIC_ORDER, 2);
1312         IBond bond = mock(IBond.class);
1313         when(bond.getOrder()).thenReturn(IBond.Order.DOUBLE);
1314         assertTrue(expr.matches(bond));
1315     }
1316 
1317     @Test
testBondOrderF()1318     public void testBondOrderF() {
1319         Expr  expr = new Expr(ALIPHATIC_ORDER, 2);
1320         IBond bond = mock(IBond.class);
1321         when(bond.getOrder()).thenReturn(IBond.Order.SINGLE);
1322         assertFalse(expr.matches(bond));
1323     }
1324 
1325     @Test
testBondOrderAlipF()1326     public void testBondOrderAlipF() {
1327         Expr  expr = new Expr(ALIPHATIC_ORDER, 2);
1328         IBond bond = mock(IBond.class);
1329         when(bond.isAromatic()).thenReturn(true);
1330         when(bond.getOrder()).thenReturn(IBond.Order.DOUBLE);
1331         assertFalse(expr.matches(bond));
1332     }
1333 
1334     @Test
testBondOrderNullF()1335     public void testBondOrderNullF() {
1336         Expr  expr = new Expr(ALIPHATIC_ORDER, 2);
1337         IBond bond = mock(IBond.class);
1338         when(bond.getOrder()).thenReturn(null);
1339         assertFalse(expr.matches(bond));
1340     }
1341 
1342     @Test
testSingleOrAromaticT()1343     public void testSingleOrAromaticT() {
1344         Expr  expr = new Expr(SINGLE_OR_AROMATIC);
1345         IBond bond = mock(IBond.class);
1346         when(bond.isAromatic()).thenReturn(false);
1347         when(bond.getOrder()).thenReturn(IBond.Order.SINGLE);
1348         assertTrue(expr.matches(bond));
1349         when(bond.isAromatic()).thenReturn(true);
1350         when(bond.getOrder()).thenReturn(null);
1351         assertTrue(expr.matches(bond));
1352     }
1353 
1354     @Test
testSingleOrAromaticF()1355     public void testSingleOrAromaticF() {
1356         Expr  expr = new Expr(SINGLE_OR_AROMATIC);
1357         IBond bond = mock(IBond.class);
1358         when(bond.isAromatic()).thenReturn(false);
1359         when(bond.getOrder()).thenReturn(IBond.Order.TRIPLE);
1360         assertFalse(expr.matches(bond));
1361     }
1362 
1363     @Test
testDoubleOrAromaticT()1364     public void testDoubleOrAromaticT() {
1365         Expr  expr = new Expr(DOUBLE_OR_AROMATIC);
1366         IBond bond = mock(IBond.class);
1367         when(bond.isAromatic()).thenReturn(true);
1368         when(bond.getOrder()).thenReturn(null);
1369         assertTrue(expr.matches(bond));
1370         when(bond.isAromatic()).thenReturn(false);
1371         when(bond.getOrder()).thenReturn(IBond.Order.DOUBLE);
1372         assertTrue(expr.matches(bond));
1373         when(bond.isAromatic()).thenReturn(false);
1374         when(bond.getOrder()).thenReturn(IBond.Order.TRIPLE);
1375         assertFalse(expr.matches(bond));
1376     }
1377 
1378     @Test
testSingleOrDoubleT()1379     public void testSingleOrDoubleT() {
1380         Expr  expr = new Expr(SINGLE_OR_DOUBLE);
1381         IBond bond = mock(IBond.class);
1382         when(bond.getOrder()).thenReturn(IBond.Order.SINGLE);
1383         assertTrue(expr.matches(bond));
1384         when(bond.getOrder()).thenReturn(IBond.Order.DOUBLE);
1385         assertTrue(expr.matches(bond));
1386         when(bond.getOrder()).thenReturn(IBond.Order.TRIPLE);
1387         assertFalse(expr.matches(bond));
1388     }
1389 
1390     @Test(expected = IllegalArgumentException.class)
testNonBondExpr()1391     public void testNonBondExpr() {
1392         Expr  expr = new Expr(RING_COUNT, 1);
1393         IBond bond = mock(IBond.class);
1394         expr.matches(bond);
1395     }
1396 
1397     @Test
testToString()1398     public void testToString() {
1399         assertThat(new Expr(TRUE).toString(), is("TRUE"));
1400         assertThat(new Expr(ELEMENT, 8).toString(), is("ELEMENT=8"));
1401         assertThat(new Expr(ELEMENT, 8).or(new Expr(DEGREE, 3)).toString(), is("OR(ELEMENT=8,DEGREE=3)"));
1402         assertThat(new Expr(ELEMENT, 8).and(new Expr(DEGREE, 3)).toString(), is("AND(ELEMENT=8,DEGREE=3)"));
1403         assertThat(new Expr(ELEMENT, 8).negate().toString(), is("NOT(ELEMENT=8)"));
1404         assertThat(new Expr(RECURSIVE, null).toString(), is("RECURSIVE(...)"));
1405     }
1406 
testNegationOptimizations()1407     @Test public void testNegationOptimizations() {
1408         assertThat(new Expr(TRUE).negate(), is(new Expr(FALSE)));
1409         assertThat(new Expr(FALSE).negate(), is(new Expr(TRUE)));
1410         assertThat(new Expr(IS_IN_RING).negate(), is(new Expr(IS_IN_CHAIN)));
1411         assertThat(new Expr(IS_IN_CHAIN).negate(), is(new Expr(IS_IN_RING)));
1412         assertThat(new Expr(IS_ALIPHATIC).negate(), is(new Expr(IS_AROMATIC)));
1413         assertThat(new Expr(IS_AROMATIC).negate(), is(new Expr(IS_ALIPHATIC)));
1414         assertThat(new Expr(ELEMENT, 8).negate(),
1415                    is(new Expr(NOT, new Expr(ELEMENT, 8), null)));
1416         assertThat(new Expr(NOT, new Expr(ELEMENT, 8), null).negate(),
1417                    is(new Expr(ELEMENT, 8)));
1418         assertThat(new Expr(HAS_UNSPEC_ISOTOPE).negate(),
1419                    is(new Expr(HAS_ISOTOPE)));
1420         assertThat(new Expr(HAS_ISOTOPE).negate(),
1421                    is(new Expr(HAS_UNSPEC_ISOTOPE)));
1422     }
1423 
testLeftBalancedOr1()1424     @Test public void testLeftBalancedOr1() {
1425         Expr expr1 = new Expr(ELEMENT, 9);
1426         Expr expr2 = new Expr(ELEMENT, 17).or(new Expr(ELEMENT, 35));
1427         expr1.or(expr2);
1428         assertThat(expr1.left().type(), is(ELEMENT));
1429     }
1430 
testLeftBalancedOr2()1431     @Test public void testLeftBalancedOr2() {
1432         Expr expr1 = new Expr(ELEMENT, 9);
1433         Expr expr2 = new Expr(ELEMENT, 17).or(new Expr(ELEMENT, 35));
1434         expr2.or(expr1);
1435         assertThat(expr2.left().type(), is(ELEMENT));
1436     }
1437 
testLeftBalancedAnd1()1438     @Test public void testLeftBalancedAnd1() {
1439         Expr expr1 = new Expr(ELEMENT, 9);
1440         Expr expr2 = new Expr(DEGREE, 2).and(new Expr(HAS_IMPLICIT_HYDROGEN));
1441         expr1.and(expr2);
1442         assertThat(expr1.left().type(), is(ELEMENT));
1443     }
1444 
testLeftBalancedAnd2()1445     @Test public void testLeftBalancedAnd2() {
1446         Expr expr1 = new Expr(ELEMENT, 9);
1447         Expr expr2 = new Expr(DEGREE, 2).and(new Expr(HAS_IMPLICIT_HYDROGEN));
1448         expr2.and(expr1);
1449         assertThat(expr2.left().type(), is(DEGREE));
1450         assertThat(expr2.right().type(), is(AND));
1451         assertThat(expr2.right().left().type(), is(HAS_IMPLICIT_HYDROGEN));
1452         assertThat(expr2.right().right().type(), is(ELEMENT));
1453     }
1454 
alwaysTrueAnd()1455     @Test public void alwaysTrueAnd() {
1456         assertThat(new Expr(TRUE).and(new Expr(TRUE)),
1457                    is(new Expr(TRUE)));
1458     }
1459 
alwaysFalseAnd()1460     @Test public void alwaysFalseAnd() {
1461         assertThat(new Expr(FALSE).and(new Expr(TRUE)),
1462                    is(new Expr(FALSE)));
1463     }
1464 
removeFalseOr()1465     @Test public void removeFalseOr() {
1466         assertThat(new Expr(DEGREE, 2).or(new Expr(FALSE)),
1467                    is(new Expr(DEGREE, 2)));
1468         assertThat(new Expr(DEGREE, 2).or(new Expr(TRUE)),
1469                    is(new Expr(DEGREE, 2)));
1470         assertThat(new Expr(FALSE).or(new Expr(DEGREE, 2)),
1471                    is(new Expr(DEGREE, 2)));
1472         assertThat(new Expr(TRUE).or(new Expr(DEGREE, 2)),
1473                    is(new Expr(DEGREE, 2)));
1474     }
1475 
1476 
1477 }