001: /*
002: * Copyright (C) 1999-2004 <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</a>
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package org.mandarax.reference.validation;
020:
021: import org.mandarax.kernel.*;
022: import org.mandarax.kernel.validation.TestCase;
023: import org.mandarax.reference.DefaultInferenceEngine;
024: import java.util.*;
025:
026: /**
027: * Default implementation of a test case, based on the JUnit framework.
028: * @author <A HREF="mailto:j.b.dietrich@massey.ac.nz">Jens Dietrich</A>
029: * @version 3.4 <7 March 05>
030: * @since 3.3.3
031: */
032: public class TestCaseImpl extends junit.framework.TestCase implements
033: TestCase {
034:
035: protected KnowledgeBase kb = null; // the kb to be tested (usually containing only rules)
036: protected ClauseSet[] assumptions = new Fact[0]; // additional assumptions
037: protected Query query = null; // the test query
038: protected int expectedNumberOfResults = -1; // -1 means that this is not checked
039: protected java.util.Map[] expectedReplacements = null; // the replacements expected in the first result, null means that this is not checked
040: protected InferenceEngine ie = new DefaultInferenceEngine();
041: private boolean mustBeTrue = false; // for ground queries
042: private Properties additionalProperties = null; // generic properties
043: private int policyToAddAssumptionsToKB = AT_BOTTOM; // policy to add assumptions to the kb
044:
045: /**
046: * Compares objects.
047: * @param obj an object
048: * @return a boolean
049: */
050: public boolean equals(Object obj) {
051: if (obj != null && obj.getClass() == this .getClass()) {
052: TestCaseImpl tc = (TestCaseImpl) obj;
053: boolean result = true; // IMPORTANT - do not compare the kbs - this is a back reference and will lead to an infinite loop
054: result = result
055: && (query == null ? tc.query == null : this .query
056: .equals(tc.query));
057: if (expectedReplacements == null)
058: result = result && tc.expectedReplacements == null;
059: else {
060: result = result
061: && expectedReplacements.length == tc.expectedReplacements.length;
062: if (result) {
063: for (int i = 0; i < expectedReplacements.length; i++) {
064: result = result
065: && expectedReplacements[i]
066: .equals(tc.expectedReplacements[i]);
067: }
068: }
069: }
070: result = result && (mustBeTrue == tc.mustBeTrue);
071: result = result
072: && (policyToAddAssumptionsToKB == tc.policyToAddAssumptionsToKB);
073: result = result
074: && expectedNumberOfResults == tc.expectedNumberOfResults;
075: result = result
076: && (getProperties() == null ? tc.getProperties() == null
077: : this .getProperties().equals(
078: tc.getProperties()));
079: return result;
080: }
081: return false;
082: }
083:
084: /**
085: * Get the hash code for this object
086: * @return an integer
087: */
088: public int hashCode() {
089: return (query == null ? 0 : query.hashCode())
090: ^ expectedNumberOfResults
091: ^ (expectedReplacements == null ? 42
092: : expectedReplacements.hashCode());
093: }
094:
095: /**
096: * Constructor.
097: * @param assumptions
098: * @param policyToAddAssumptionsToKB
099: * @param query
100: * @param expectedNumberOfResults
101: * @param expectedReplacements
102: * @param mustBeTrue
103: */
104: public TestCaseImpl(ClauseSet[] assumptions,
105: int policyToAddAssumptionsToKB, Query query,
106: int expectedNumberOfResults,
107: java.util.Map[] expectedReplacements, boolean mustBeTrue) {
108: super ("execute");
109: this .assumptions = assumptions;
110: this .policyToAddAssumptionsToKB = policyToAddAssumptionsToKB;
111: this .query = query;
112: this .expectedNumberOfResults = expectedNumberOfResults;
113: this .expectedReplacements = expectedReplacements;
114: this .mustBeTrue = mustBeTrue;
115: }
116:
117: /**
118: * Constructor.
119: * @param assumptions
120: * @param policyToAddAssumptionsToKB
121: * @param query
122: * @param expectedNumberOfResults
123: */
124: public TestCaseImpl(ClauseSet[] assumptions,
125: int policyToAddAssumptionsToKB, Query query,
126: int expectedNumberOfResults) {
127: super ("execute");
128: this .assumptions = assumptions;
129: this .policyToAddAssumptionsToKB = policyToAddAssumptionsToKB;
130: this .query = query;
131: this .expectedNumberOfResults = expectedNumberOfResults;
132:
133: }
134:
135: /**
136: * Constructor.
137: * @param assumptions
138: * @param policyToAddAssumptionsToKB
139: * @param query
140: * @param expectedReplacements
141: */
142: public TestCaseImpl(ClauseSet[] assumptions,
143: int policyToAddAssumptionsToKB, Query query,
144: java.util.Map[] expectedReplacements) {
145: super ("execute");
146: this .assumptions = assumptions;
147: this .policyToAddAssumptionsToKB = policyToAddAssumptionsToKB;
148: this .query = query;
149: this .expectedReplacements = expectedReplacements;
150: }
151:
152: /**
153: * Constructor.
154: * @param assumptions
155: * @param policyToAddAssumptionsToKB
156: * @param query
157: * @param expectedNumberOfResults
158: * @param expectedReplacements
159: * @param mustBeTrue
160: */
161: public TestCaseImpl(ClauseSet[] assumptions,
162: int policyToAddAssumptionsToKB, Query query,
163: boolean mustBeTrue) {
164: super ("execute");
165: this .assumptions = assumptions;
166: this .policyToAddAssumptionsToKB = policyToAddAssumptionsToKB;
167: this .query = query;
168: this .mustBeTrue = mustBeTrue;
169: }
170:
171: /**
172: * Tears down the test case.
173: */
174: protected void tearDown() throws Exception {
175: for (int i = 0; i < assumptions.length; i++)
176: this .kb.remove(assumptions[i]);
177: super .tearDown();
178: }
179:
180: /**
181: * Sets up down the test case.
182: */
183: protected void setUp() throws Exception {
184: super .setUp();
185: if (this .policyToAddAssumptionsToKB == AT_BOTTOM)
186: for (int i = 0; i < assumptions.length; i++)
187: this .kb.add(assumptions[i]);
188: if (this .policyToAddAssumptionsToKB == ON_TOP
189: && kb instanceof ExtendedKnowledgeBase) {
190: ExtendedKnowledgeBase xkb = (ExtendedKnowledgeBase) kb;
191: for (int i = assumptions.length - 1; i > -1; i--) {
192: xkb.add(assumptions[i]);
193: xkb.moveToTop(assumptions[i]);
194: }
195: }
196: }
197:
198: /**
199: * Prepares the test case.
200: */
201: public void prepare() throws Exception {
202: this .setUp();
203: }
204:
205: /**
206: * Releases the test case.
207: */
208: public void release() throws Exception {
209: this .release();
210: }
211:
212: /**
213: * Tests the knowledge base.
214: */
215: public void execute() throws Exception {
216:
217: ResultSet rs = ie.query(query, kb, InferenceEngine.ALL,
218: InferenceEngine.BUBBLE_EXCEPTIONS);
219: int counter = 0;
220: boolean finalResult = true;
221:
222: // 1. ground queries
223: if (query.isGround()) {
224: boolean ok = rs.next() == this .mustBeTrue;
225: counter = counter + 1;
226: if (ok)
227: finalResult = finalResult && ok;
228: else
229: assertTrue(mustBeTrue ? "Ground query should be valid"
230: : "Ground query should not be valid", ok);
231: }
232:
233: // 2. non-ground queries
234: else if (this .expectedReplacements != null
235: && this .expectedReplacements.length > 0) {
236: for (int i = 0; i < expectedReplacements.length; i++) {
237: java.util.Map map = this .expectedReplacements[i];
238: rs.next();
239: counter = counter + 1;
240: for (Iterator keys = map.keySet().iterator(); keys
241: .hasNext();) {
242: VariableTerm var = (VariableTerm) keys.next();
243: Object computed = rs.getResult(var);
244: Object expected = map.get(var);
245: if (!expected.equals(computed)) {
246: StringBuffer buf = new StringBuffer().append(
247: "In result ").append(counter).append(
248: " ").append(expected).append(
249: " was expected but ").append(computed)
250: .append(" was found as result for ")
251: .append(var);
252: assertTrue(buf.toString(), false);
253: }
254: }
255: }
256: }
257:
258: // 3. Count results
259: if (this .expectedNumberOfResults > -1) {
260: while (rs.next())
261: counter = counter + 1;
262: if (expectedNumberOfResults != counter) {
263: StringBuffer buf = new StringBuffer().append(
264: "Expected number of results is ").append(
265: expectedNumberOfResults).append(" but ")
266: .append(counter).append(" results found ");
267: assertTrue(buf.toString(), false);
268: }
269: }
270: rs.close();
271:
272: assertTrue(true);
273:
274: }
275:
276: /**
277: * Get the assumptions.
278: * @return Returns the assumptions.
279: */
280: public ClauseSet[] getAssumptions() {
281: return assumptions;
282: }
283:
284: /**
285: * Set the assumptions.
286: * @param assumptions The assumptions to set.
287: */
288: public void setAssumptions(ClauseSet[] assumptions) {
289: this .assumptions = assumptions;
290: }
291:
292: /**
293: * @return Returns the kb.
294: */
295: public KnowledgeBase getKb() {
296: return kb;
297: }
298:
299: /**
300: * Set the kb. Called by the kb when adding the test case to the kb to insert a back reference.
301: * @param kb The kb to set.
302: */
303: public void setKb(KnowledgeBase kb) {
304: this .kb = kb;
305: }
306:
307: /**
308: * Get the test query.
309: * @return Returns the query.
310: */
311: public Query getQuery() {
312: return query;
313: }
314:
315: /**
316: * Set the test query.
317: * @param query The query to set.
318: */
319: public void setQuery(Query query) {
320: this .query = query;
321: }
322:
323: /**
324: * @return Returns the expectedNumberOfResults.
325: */
326: public int getExpectedNumberOfResults() {
327: return expectedNumberOfResults;
328: }
329:
330: /**
331: * @param expectedNumberOfResults The expectedNumberOfResults to set.
332: */
333: public void setExpectedNumberOfResults(int expectedNumberOfResults) {
334: this .expectedNumberOfResults = expectedNumberOfResults;
335: }
336:
337: /**
338: * Get an array of maps containing variable term -> constant term mapping expected in the result
339: * at this position.
340: * Can be null indicating that this condition will not be checked in this test case.
341: * @return Returns the expectedReplacements.
342: */
343: public java.util.Map[] getExpectedReplacements() {
344: return expectedReplacements;
345: }
346:
347: /**
348: * Set an array of maps containing variable term -> constant term mapping expected in the result
349: * at this position.
350: * Can be null indicating that this condition will not be checked in this test case.
351: * @param expectedReplacements The expectedReplacements to set.
352: */
353: public void setExpectedReplacements(
354: java.util.Map[] expectedReplacements) {
355: this .expectedReplacements = expectedReplacements;
356: }
357:
358: /**
359: * Indicates whether a test case must yield true.
360: * Only used if the query is ground (does not have variables).
361: * @return Returns the mustBeTrue.
362: */
363: public boolean isMustBeTrue() {
364: return mustBeTrue;
365: }
366:
367: /**
368: * Sets whether a test case must yield true.
369: * Only used if the query is ground (does not have variables).
370: * @param mustBeTrue The mustBeTrue to set.
371: */
372: public void setMustBeTrue(boolean mustBeTrue) {
373: this .mustBeTrue = mustBeTrue;
374: }
375:
376: /**
377: * Set a property.
378: * @param key the key
379: * @param value the value
380: * @return the previous value of the specified key in this property list, or null if it did not have one.
381: */
382: public Object setProperty(String key, String value) {
383: if (additionalProperties == null)
384: additionalProperties = new Properties();
385: return additionalProperties.setProperty(key, value);
386: }
387:
388: /**
389: * Get a property.
390: * @param key the property key
391: * @return the respective value. The method returns null if the property is not found.
392: */
393: public String getProperty(String key) {
394: if (additionalProperties == null)
395: additionalProperties = new Properties();
396: return additionalProperties.getProperty(key);
397: }
398:
399: /**
400: * Returns an enumeration of all the keys in this property list, including distinct
401: * keys in the default property list if a key of the same name has not already been
402: * found from the main properties list.
403: * @return an enumeration of all the keys in this property list, including the keys in
404: * the default property list
405: */
406: public Enumeration propertyNames() {
407: if (additionalProperties == null)
408: additionalProperties = new Properties();
409: return additionalProperties.propertyNames();
410: }
411:
412: /**
413: * Remove a property.
414: * @param key the property key
415: * @return the value to which the key had been mapped, or null if the key did not have a mapping.
416: */
417: public Object removeProperty(String key) {
418: if (additionalProperties != null)
419: return additionalProperties.remove(key);
420: return null;
421: }
422:
423: /**
424: * Get the properties as one "properties" instance.
425: * @return a properties instance
426: */
427: public Properties getProperties() {
428: if (additionalProperties == null)
429: additionalProperties = new Properties();
430: return additionalProperties;
431: };
432:
433: /**
434: * Set the properties. Not required by the interface, but useful for bean (introspection-) based
435: * tools.
436: * @param properties the properties
437: */
438: public void setProperties(Properties properties) {
439: additionalProperties = properties;
440: };
441:
442: /**
443: * Set the policy to add an assumption.
444: * @param policy the (encoded) policy = one of the constants defined in TestCase
445: */
446: public void setPolicyToAddAssumptionsToKB(int policy) {
447: policyToAddAssumptionsToKB = policy;
448: }
449:
450: /**
451: * Get the policy to add an assumption.
452: * @return an integer, the (encoded) policy = one of the constants defined in TestCase
453: */
454: public int getPolicyToAddAssumptionsToKB() {
455: return policyToAddAssumptionsToKB;
456: }
457: }
|