001: /**
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */package com.tc.util;
005:
006: import java.util.Arrays;
007: import java.util.Collection;
008: import java.util.Iterator;
009:
010: /**
011: * A general purpose assertion utility. By default it is on, but you can disable the throwing of exceptions by giving
012: * the system property "tcassert" a value of 'false'.
013: */
014: public class Assert {
015:
016: private static final String ASSERT_PROPERTY_NAME = "tcassert";
017:
018: // When (if) we want to run *without* assertions enabled by default, use the line below to initialize instead
019: // private static final boolean enabled = Boolean.getBoolean(ASSERT_PROPERTY_NAME);
020: //
021: // NOTE: We need to be VERY careful about casually turning off assertions. It's one thing to make the assertions not
022: // throw errors (which the current disable/enable mechanism does). It's entirely something different to remove the
023: // calls to assertions. At the time of this writing, there are state modifying method calls in the code base that are
024: // paremeters to these assert method. Removing the call altogher would most certainly change the logic of the system
025: // in potentially silent and catastropic ways
026: private static final boolean enabled = Boolean.valueOf(
027: System.getProperty(ASSERT_PROPERTY_NAME, "true"))
028: .booleanValue();
029:
030: private static boolean isEnabled() {
031: return enabled;
032: }
033:
034: /**
035: * This returns an exception, instead of throwing one, so that you can do (e.g.): <code>
036: * public Object foo() { throw Assert.failure("doesn't work"); }
037: * </code>
038: * or whatever. If this just threw the exception itself, the compiler would complain (above) that there's no value
039: * being returned.
040: *
041: * @param message The message to put in the assertion error
042: * @param t The exception to wrap
043: * @return New TCAssertionError, ready to throw
044: */
045: public static TCAssertionError failure(Object message, Throwable t) {
046: return new TCAssertionError(StringUtil.safeToString(message), t);
047: }
048:
049: /**
050: * This returns an exception, instead of throwing one, so that you can do (e.g.): <code>
051: * public Object foo() { throw Assert.failure("doesn't work"); }
052: * </code>
053: * or whatever. If this just threw the exception itself, the compiler would complain (above) that there's no value
054: * being returned.
055: *
056: * @param message The message to put in the assertion error
057: * @return New TCAssertionError, ready to throw
058: */
059: public static TCAssertionError failure(Object message) {
060: return new TCAssertionError(StringUtil.safeToString(message));
061: }
062:
063: /**
064: * Evaluate the boolean exception and throw an assertion error if false
065: *
066: * @param expr Expression
067: */
068: public static void eval(boolean expr) {
069: if ((!expr) && isEnabled()) {
070: throw failure("Assertion failed");
071: }
072: return;
073: }
074:
075: /**
076: * Evaluate the boolean exception and throw an assertion error if false
077: *
078: * @param expr Expression
079: * @param message Message for assertion error if false
080: */
081: public static void eval(Object message, boolean expr) {
082: if ((!expr) && isEnabled()) {
083: throw failure("Assertion failed: "
084: + StringUtil.safeToString(message));
085: }
086: return;
087: }
088:
089: /**
090: * Evaluate the boolean exception and throw an assertion error if false
091: *
092: * @param expr Expression
093: */
094: public static void assertTrue(boolean expr) {
095: eval(expr);
096: }
097:
098: /**
099: * Evaluate the boolean exception and throw an assertion error if false
100: *
101: * @param expr Expression
102: * @param message Message for assertion error if false
103: */
104: public static void assertTrue(Object message, boolean expr) {
105: eval(message, expr);
106: }
107:
108: /**
109: * Evaluate the boolean exception and throw an assertion error if true
110: *
111: * @param expr Expression
112: * @param message Message for assertion error if true
113: */
114: public static void assertFalse(boolean expr) {
115: eval(!expr);
116: }
117:
118: /**
119: * Evaluate the boolean exception and throw an assertion error if true
120: *
121: * @param expr Expression
122: * @param message Message for assertion error if true
123: */
124: public static void assertFalse(Object message, boolean expr) {
125: eval(message, !expr);
126: }
127:
128: /**
129: * If o is non-null, throw assertion error
130: *
131: * @param o Object
132: */
133: public static void assertNull(Object o) {
134: assertNull("object", o);
135: }
136:
137: /**
138: * If o is non-null, throw assertion error
139: *
140: * @param o Object
141: * @param what Message for error
142: */
143: public static void assertNull(Object what, Object o) {
144: if ((o != null) && isEnabled()) {
145: throw failure(StringUtil.safeToString(what)
146: + " was not null");
147: }
148: }
149:
150: /**
151: * If o is null, throw assertion error with message what
152: *
153: * @param o Object
154: * @param what Message for error
155: */
156: public static void assertNotNull(Object what, Object o) {
157: if ((o == null) && isEnabled()) {
158: throw new NullPointerException(StringUtil
159: .safeToString(what)
160: + " is null");
161: }
162: }
163:
164: /**
165: * If o is null, throw assertion error
166: *
167: * @param o Object
168: */
169: public static void assertNotNull(Object o) {
170: assertNotNull("object", o);
171: }
172:
173: /**
174: * Validate that the given (1 dimensional) array of references contains no nulls
175: *
176: * @param array Array
177: */
178: public static void assertNoNullElements(Object[] array) {
179: if (!isEnabled())
180: return;
181: assertNotNull(array);
182:
183: for (int i = 0; i < array.length; i++) {
184: assertNotNull("item " + i, array[i]);
185: }
186: }
187:
188: /**
189: * Validate that the given array of strings contains no nulls or empty strings
190: *
191: * @param array Array of strings
192: */
193: public static void assertNoBlankElements(String[] array) {
194: if (!isEnabled())
195: return;
196: assertNotNull(array);
197:
198: for (int i = 0; i < array.length; ++i)
199: assertNotBlank(array[i]);
200: }
201:
202: /**
203: * Validate that s is not null or empty and throw what as a message
204: *
205: * @param s String
206: * @param what Message
207: */
208: public static void assertNotEmpty(Object what, String s) {
209: assertNotNull(what, s);
210: if ((s.length() == 0) && isEnabled())
211: throw new IllegalArgumentException(StringUtil
212: .safeToString(what)
213: + " is empty");
214: }
215:
216: /**
217: * Validate that s is not null or empty
218: *
219: * @param s String
220: */
221: public static void assertNotEmpty(String s) {
222: assertNotEmpty("string", s);
223: }
224:
225: /**
226: * Validate that s is not blank and throw what as a message
227: *
228: * @param s String
229: * @param what Message
230: */
231: public static void assertNotBlank(Object what, String s) {
232: assertNotEmpty(what, s);
233: if ((s.trim().length() == 0) && isEnabled())
234: throw new IllegalArgumentException(StringUtil
235: .safeToString(what)
236: + " is blank");
237: }
238:
239: /**
240: * Validate that s is not blank
241: *
242: * @param s String
243: */
244: public static void assertNotBlank(String s) {
245: assertNotBlank("string", s);
246: }
247:
248: /**
249: * Validate that lhs and rhs are identical object references or both are null
250: *
251: * @param lhs Left hand side
252: * @param rhs Right hand side
253: */
254: public static void assertSame(Object lhs, Object rhs) {
255: if (lhs == null) {
256: eval("leftHandSide == null, but rightHandSide != null",
257: rhs == null);
258: } else {
259: eval("leftHandSide != null, but rightHandSide == null",
260: rhs != null);
261: eval("leftHandSide != rightHandSide", lhs == rhs);
262: }
263: }
264:
265: /**
266: * Assert expected and actual values are equal
267: *
268: * @param expected Expected value
269: * @param actual Actual value
270: */
271: public static void assertEquals(int expected, int actual) {
272: if (expected != actual) {
273: throw new TCAssertionError("Expected <" + expected
274: + "> but got <" + actual + ">");
275: }
276: }
277:
278: /**
279: * Assert expected and actual values are equal and return what as a message
280: *
281: * @param expected Expected value
282: * @param actual Actual value
283: * @param msg Message, should be non-null
284: */
285: public static void assertEquals(Object msg, int expected, int actual) {
286: if (expected != actual) {
287: throw new TCAssertionError(msg + ": Expected <" + expected
288: + "> but got <" + actual + ">");
289: }
290: }
291:
292: /**
293: * Assert expected and actual values are equal
294: *
295: * @param expected Expected value
296: * @param actual Actual value
297: */
298: public static void assertEquals(double expected, double actual) {
299: if (expected != actual) {
300: throw new TCAssertionError("Expected <" + expected
301: + "> but got <" + actual + ">");
302: }
303: }
304:
305: /**
306: * Assert expected and actual values are equal within epsilon
307: *
308: * @param expected Expected value
309: * @param actual Actual value
310: * @param epsilon Maximum allowed difference between expected and actual
311: */
312: public static void assertEquals(double expected, double actual,
313: double epsilon) {
314: if (Math.abs(actual - expected) > Math.abs(epsilon)) {
315: throw new TCAssertionError("Expected <" + expected
316: + "> but got <" + actual + ">");
317: }
318: }
319:
320: /**
321: * Assert expected and actual values are equal
322: *
323: * @param expected Expected value
324: * @param actual Actual value
325: */
326: public static void assertEquals(boolean expected, boolean actual) {
327: if (expected != actual) {
328: throw new TCAssertionError("Expected <" + expected
329: + "> but got <" + actual + ">");
330: }
331: }
332:
333: /**
334: * Assert expected and actual values are equal or both null
335: *
336: * @param expected Expected value
337: * @param actual Actual value
338: */
339: public static void assertEquals(byte[] expected, byte[] actual) {
340: boolean expr = (expected == null) ? actual == null : Arrays
341: .equals(expected, actual);
342: if (!expr) {
343: throw new TCAssertionError("Expected <" + expected
344: + "> but got <" + actual + ">");
345: }
346: }
347:
348: /**
349: * Assert expected and actual values are equal or both null
350: *
351: * @param expected Expected value
352: * @param actual Actual value
353: */
354: public static void assertEquals(Object expected, Object actual) {
355: assertEquals(null, expected, actual);
356: }
357:
358: public static void assertEquals(Object msg, Object expected,
359: Object actual) {
360: boolean expr = (expected == null) ? actual == null : expected
361: .equals(actual);
362: if (!expr) {
363: throw new TCAssertionError(
364: (msg != null ? (msg + ": ") : "") + "Expected <"
365: + expected + "> but got <" + actual + ">");
366: }
367: }
368:
369: /**
370: * Assert that all items in collection are of type elementClass, also if !allowNullElements, check that all items in
371: * the collection are non-null.
372: *
373: * @param collection The collection
374: * @param elementClass The expected super type of all items in collection
375: * @param allowNullElements Flag for whether null elements are allowed or not
376: */
377: public static void assertConsistentCollection(
378: Collection collection, Class elementClass,
379: boolean allowNullElements) {
380: assertNotNull("Collection", collection);
381: assertNotNull("Element class", elementClass);
382: for (Iterator pos = collection.iterator(); pos.hasNext();) {
383: Object element = pos.next();
384: if (!allowNullElements) {
385: assertNotNull(element);
386: }
387: if (element != null) {
388: eval("Element '" + element
389: + "' is not an instance of '"
390: + elementClass.getName() + "'", elementClass
391: .isInstance(element));
392: }
393: }
394: }
395:
396: /**
397: * Tests for equality using the <code>==</code> operator, <em>not</em> <code>Object.equals(Object)</code>.
398: * <code>null</code> is a valid element.
399: *
400: * @param objectArray Array of objects
401: * @param requiredElement Must be in objectArray
402: */
403: public static void assertContainsElement(Object[] objectArray,
404: Object requiredElement) {
405: assertNotNull(objectArray);
406: for (int pos = 0; pos < objectArray.length; pos++) {
407: if (objectArray[pos] == requiredElement)
408: return;
409: }
410: throw failure("Element<" + requiredElement
411: + "> not found in array "
412: + StringUtil.toString(objectArray, ",", "<", ">"));
413: }
414:
415: /**
416: * Throw assertion error with generic message
417: */
418: public static void fail() {
419: throw failure("generic failure");
420: }
421:
422: /**
423: * Throw assertion error with specified message
424: *
425: * @param message Message
426: */
427: public static void fail(String message) {
428: throw failure(message);
429: }
430:
431: /**
432: * Assert precondition
433: *
434: * @param v Precondition
435: */
436: public static void pre(boolean v) {
437: if (!v)
438: throw new TCAssertionError("Precondition failed");
439: }
440:
441: /**
442: * Assert postcondition
443: *
444: * @param v Postcondition
445: */
446: public static void post(boolean v) {
447: if (!v)
448: throw new TCAssertionError("Postcondition failed");
449: }
450:
451: /**
452: * Assert invariant
453: *
454: * @param v Invariant
455: */
456: public static void inv(boolean v) {
457: if (!v)
458: throw new TCAssertionError("Invariant failed");
459: }
460: }
|