From 9258a861ce9acb7a6f380c0db8fce481cacfc5f0 Mon Sep 17 00:00:00 2001
From: davidely <davidely@localhost>
Date: Tue, 10 Oct 2006 00:27:04 +0000
Subject: [PATCH] Added ensureNotNull and ensureTrue functionality via the new Validator class. Thanks to Neil and Andy for the reviews.

---
 opendj-sdk/opends/src/server/org/opends/server/messages/UtilityMessages.java                    |   13 +
 opendj-sdk/opends/src/server/org/opends/server/util/Validator.java                              |  479 +++++++++++++++++++++++++++++++++++++++++++
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/util/ValidatorTests.java |  167 +++++++++++++++
 3 files changed, 659 insertions(+), 0 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/messages/UtilityMessages.java b/opendj-sdk/opends/src/server/org/opends/server/messages/UtilityMessages.java
index b3dafb2..d6be681 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/messages/UtilityMessages.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/messages/UtilityMessages.java
@@ -1583,6 +1583,14 @@
        CATEGORY_MASK_UTIL | SEVERITY_MASK_MILD_ERROR | 147;
 
 
+  /**
+   * The message ID for the message that will be used if a Validator check
+   * fails.  This signals that there is a method invocation that violates
+   * the pre-conditions of the method.
+   */
+  public static final int MSGID_VALIDATOR_PRECONDITION_NOT_MET =
+       CATEGORY_MASK_UTIL | SEVERITY_MASK_SEVERE_ERROR | 148;
+
 
   /**
    * Associates a set of generic messages with the message IDs defined in this
@@ -2108,6 +2116,11 @@
                     "file mode.  UNIX file modes must be a three-character " +
                     "string in which each character is a numeric digit " +
                     "between zero and seven.");
+
+    registerMessage(MSGID_VALIDATOR_PRECONDITION_NOT_MET,
+                    "A precondition of the invoked method was not met.  This " +
+                    "This usually means there is a defect somewhere in the " +
+                    "call stack.  Details: %s");
   }
 }
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/Validator.java b/opendj-sdk/opends/src/server/org/opends/server/util/Validator.java
new file mode 100644
index 0000000..223ccd6
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/Validator.java
@@ -0,0 +1,479 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+package org.opends.server.util;
+
+import static org.opends.server.loggers.Debug.debugMessage;
+import org.opends.server.types.DebugLogCategory;
+import org.opends.server.types.DebugLogSeverity;
+import org.opends.server.types.ErrorLogCategory;
+import org.opends.server.types.ErrorLogSeverity;
+import org.opends.server.messages.UtilityMessages;
+
+/**
+ * This utility class provides static methods that make parameter checking
+ * easier (e.g. in constructors and setters).
+ * In particular the ensureNotNull methods provide an easy way to validate that
+ * certain parameters are not null, and the ensureTrue methods provide the
+ * ability to check arbitrary boolean conditions.
+ * <p>
+ * Invocation of these methods should be limited to situations where the only
+ * way that they should fail is if there is a defect somewhere in the
+ * system (including 3rd-party plugins).
+ * <p>
+ * You can think of these methods as being similar to <code>assert</code>,
+ * but there are some additional advantages:
+ * <ul>
+ *   <li>All failures are logged to the debug and error logs</li>
+ *   <li>Checks are always enabled (even if asserts are off)</li>
+ *   <li>This class tracks the number of failures, allowing it to
+ *       be exposed via monitoring, etc.<li>
+ *   <li>The unit tests can track unnoticed internal failures and
+ *       report on them.</li>
+ *   <li>Developers can catch all Validator failures with a single
+ *       break point.</li>
+ * </ul>
+ *
+ * In general, you should not worry about the performance impact of calling
+ * these methods.  Some micro-benchmarking has shown that ensureNotNull can be
+ * called 200M times per second on a single CPU laptop.  The value of catching
+ * defects early will almost always out-weigh any overhead that is introduced.
+ * There are a couple of exceptions to this.  Any execution overhead that
+ * happens before the method is invoked cannot be eliminated, e.g.
+ * <code>Validator.ensureTrue(someExpensiveCheck())</code> will always invoke
+ * <code>someExpensiveCheck()</code>.  When this code is on the critical path,
+ * and we do not expect the validation to failure, you can guard the call with
+ * an <code>assert</code> because each method returns true, and this code will
+ * only be executed when asserts are enabled.
+ * <p>
+ * These methods are provided primarily to check parameter values for
+ * constructors, setters, etc, and when they are used in this way, the javadoc
+ * for the method must be updated to reflect what constraints are placed on the
+ * parameters (e.g. attributeType cannot be null).
+ * <p>
+ * Feel free to add any method to this class that makes sense.  Be sure to
+ * ensure that they don't violate the spirit of this class in that performance
+ * is second only to correctness.
+ * <p>
+ * There are a few issues open for remaining tasks:
+ * <ul>
+ *  <li>757 Validator should expose a way to turn it off</li>
+ *  <li>758 Validator should provide a way to throttle it's error messages</li>
+ *  <li>759 Unit tests should always check that no unexpected Validator checks
+ *      failed</li>
+ * </ul>
+ */
+public class Validator {
+  /** This static final variable theoretically allows us to compile out all of
+   *  these checks.  Since all of the code below is guarded with this check,
+   *  the compiler should eliminate it if ENABLE_CHECKS is false.
+   *  From doing a little bit of micro-benchmarking, it appears that setting
+   *  ENABLE_CHECKS=false speeds the code up by about a factor of four, but
+   *  it's still not the same as not having the invocation in the first place.
+   *  On a single CPU laptop, I was able to get 200M
+   *  invocations per second with ENABLE_CHECKS=true, and 350M with
+   *  ENABLE_CHECKS=false.
+   *  <p>
+   *  Setting this to false, will not eliminate any expensive computation
+   *  done in a parameter list (e.g. some self-check that returns true).*/
+  public static final boolean ENABLE_CHECKS = true;
+
+
+  /** The fully-qualified class name for this class, which is used for
+   *  debugging purposes. */
+  private static final String CLASS_NAME = Validator.class.getName();
+
+
+  /** A one-based array for parameter descriptions. */
+  private static final String[] PARAM_DESCRIPTIONS =
+          {"** A ZERO-BASED INDEX IS INVALID **",
+           "(1st parameter)",
+           "(2nd parameter)",
+           "(3rd parameter)",
+           "(4th parameter)",
+           "(5th parameter)",
+           "(6th parameter)",
+           "(7th parameter)",
+           "(8th parameter)",
+           "(9th parameter)",
+           "(10th parameter)"};
+
+  /** A count of the errors detected by the methods in this class since the
+   *  last time that resetErrorCount was called.  */
+  private static long _errorCount = 0;
+
+
+  /**
+   * This method validates that the specified parameter is not null.  It
+   * throws a RuntimeException or AssertionError if it is null after logging
+   * this error.
+   * <p>
+   * This should be used like an assert, except it is not turned
+   * off at runtime.  That is, it should only be used in situations where
+   * there is a bug in someone's code if param is null.
+   *
+   * @param param the parameter to validate as non-null.
+   * @return true always.  This allows this call to be used in an assert
+   * statement, which can skip this check and remove all
+   * overhead from the calling code.  This idiom should only be used when
+   * performance testing proves that it is necessary.
+   *
+   * @throws NullPointerException if and only if param is null
+   * @throws AssertionError this is thrown instead of NullPointerException
+   * if assertions are enabled
+   */
+  public static boolean ensureNotNull(Object param)
+          throws NullPointerException, AssertionError {
+    if (ENABLE_CHECKS) {
+      if (param == null) throwNull("");
+    }
+    return true;
+  }
+
+
+
+  /**
+   * This method validates that the specified parameters are not null.  It
+   * throws a RuntimeException or AssertionError if one of them are null
+   * after logging this error.  It's similar to the ensureNotNull(Object)
+   * call except it provides the convenience of checking two parameters
+   * at once.
+   * <p>
+   * This should be used like an assert, except it is not turned
+   * off at runtime.  That is, it should only be used in situations where
+   * there is a bug in someone's code if param is null.
+   * <p>
+   * See the class level javadoc for why we did not use varargs to
+   * implement this method.
+   *
+   * @param param1 the first parameter to validate as non-null.
+   * @param param2 the second parameter to validate as non-null.
+   * @return true always.  This allows this call to be used in an assert
+   * statement, which can skip this check and remove all
+   * overhead from the calling code.  This idiom should only be used when
+   * performance testing proves that it is necessary.
+   *
+   * @throws NullPointerException if and only if one of the parameters is null
+   * @throws AssertionError this is thrown instead of NullPointerException
+   * if assertions are enabled
+   */
+  public static boolean ensureNotNull(Object param1, Object param2)
+          throws NullPointerException, AssertionError {
+    if (ENABLE_CHECKS) {
+      if (param1 == null) throwNull(PARAM_DESCRIPTIONS[1]);
+      if (param2 == null) throwNull(PARAM_DESCRIPTIONS[2]);
+    }
+    return true;
+  }
+
+
+
+  /**
+   * This method validates that the specified parameters are not null.  It
+   * throws a RuntimeException or AssertionError if one of them are null
+   * after logging this error.  It's similar to the ensureNotNull(Object)
+   * call except it provides the convenience of checking three parameters
+   * at once.
+   * <p>
+   * This should be used like an assert, except it is not turned
+   * off at runtime.  That is, it should only be used in situations where
+   * there is a bug in someone's code if param is null.
+   * <p>
+   * See the class level javadoc for why we did not use varargs to
+   * implement this method.
+   *
+   * @param param1 the first parameter to validate as non-null.
+   * @param param2 the second parameter to validate as non-null.
+   * @param param3 the third parameter to validate as non-null.
+   * @return true always.  This allows this call to be used in an assert
+   * statement, which can skip this check and remove all
+   * overhead from the calling code.  This idiom should only be used when
+   * performance testing proves that it is necessary.
+   *
+   * @throws NullPointerException if and only if one of the parameters is null
+   * @throws AssertionError this is thrown instead of NullPointerException
+   * if assertions are enabled
+   */
+  public static boolean ensureNotNull(Object param1, Object param2,
+                                      Object param3)
+          throws NullPointerException, AssertionError {
+    if (ENABLE_CHECKS) {
+      if (param1 == null) throwNull(PARAM_DESCRIPTIONS[1]);
+      if (param2 == null) throwNull(PARAM_DESCRIPTIONS[2]);
+      if (param3 == null) throwNull(PARAM_DESCRIPTIONS[3]);
+    }
+    return true;
+  }
+
+
+
+  /**
+   * This method validates that the specified parameters are not null.  It
+   * throws a RuntimeException or AssertionError if one of them are null
+   * after logging this error.  It's similar to the ensureNotNull(Object)
+   * call except it provides the convenience of checking three parameters
+   * at once.
+   * <p>
+   * This should be used like an assert, except it is not turned
+   * off at runtime.  That is, it should only be used in situations where
+   * there is a bug in someone's code if param is null.
+   * <p>
+   * See the class level javadoc for why we did not use varargs to
+   * implement this method.
+   *
+   * @param param1 the first parameter to validate as non-null.
+   * @param param2 the second parameter to validate as non-null.
+   * @param param3 the third parameter to validate as non-null.
+   * @param param4 the fourth parameter to validate as non-null.
+   * @return true always.  This allows this call to be used in an assert
+   * statement, which can skip this check and remove all
+   * overhead from the calling code.  This idiom should only be used when
+   * performance testing proves that it is necessary.
+   *
+   * @throws NullPointerException if and only if one of the parameters is null
+   * @throws AssertionError this is thrown instead of NullPointerException
+   * if assertions are enabled
+   */
+  public static boolean ensureNotNull(Object param1, Object param2,
+                                      Object param3, Object param4)
+          throws NullPointerException, AssertionError {
+    if (ENABLE_CHECKS) {
+      if (param1 == null) throwNull(PARAM_DESCRIPTIONS[1]);
+      if (param2 == null) throwNull(PARAM_DESCRIPTIONS[2]);
+      if (param3 == null) throwNull(PARAM_DESCRIPTIONS[3]);
+      if (param4 == null) throwNull(PARAM_DESCRIPTIONS[4]);
+    }
+    return true;
+  }
+
+
+  /**
+   * This method validates that the specified parameter is true.  It
+   * throws a RuntimeException or AssertionError if it is not true.
+   * <p>
+   * This should be used like an assert, except it is not turned
+   * off at runtime.  That is, it should only be used in situations where
+   * there is a bug in someone's code if param is null.  The other advantage of
+   * using this method instead of an assert is that it logs the error to the
+   * debug and error logs.
+   *
+   * @param condition the condition that must be true.
+   * @return true always.  This allows this call to be used in an assert
+   * statement, which can skip this check and remove all
+   * overhead from the calling code.  This idiom should only be used when
+   * performance testing proves that it is necessary.
+   *
+   * @throws AssertionError if condition is false and assertions are enabled
+   * @throws IllegalArgumentException if condition is false and assertions are
+   * not enabled
+   */
+  public static boolean ensureTrue(boolean condition)
+          throws IllegalArgumentException, AssertionError {
+    if (ENABLE_CHECKS) {
+      if (!condition) {
+        ensureTrue(condition, "");
+      }
+    }
+    return true;
+  }
+
+
+
+  /**
+   * This method validates that the specified parameter is true.  It
+   * throws a RuntimeException or AssertionError if it is not true.
+   * The supplied message is included in the error message.
+   * <p>
+   * This should be used like an assert, except it is not turned
+   * off at runtime.  That is, it should only be used in situations where
+   * there is a bug in someone's code if param is null.  The other advantage of
+   * using this method instead of an assert is that it logs the error to the
+   * debug and error logs.
+   *
+   * @param condition the condition that must be true.
+   * @param message the textual message to include in the error message.
+   * @return true always.  This allows this call to be used in an assert
+   * statement, which can skip this check and remove all
+   * overhead from the calling code.  This idiom should only be used when
+   * performance testing proves that it is necessary.
+   *
+   * @throws AssertionError if condition is false and assertions are enabled
+   * @throws IllegalArgumentException if condition is false and assertions are
+   * not enabled
+   */
+  public static boolean ensureTrue(boolean condition, String message)
+          throws IllegalArgumentException, AssertionError {
+    if (ENABLE_CHECKS) {
+      if (!condition) {
+        String fullMessage = generateLineSpecificErrorMessage(
+                "The specified condition must be true. " + message);
+
+        logError(fullMessage);
+
+        // Prefer throwing an assertion if they are enabled.
+        assert condition : fullMessage;
+
+        throw new IllegalArgumentException(fullMessage);
+      }
+    }
+    return true;
+  }
+
+  ////////////////////////////////////////////////////////////////////////////
+  //
+  //  ERROR COUNT
+  //
+  ////////////////////////////////////////////////////////////////////////////
+
+
+  /**
+   * Returns the number of errors that this class has detected since the
+   * system started or the last time that resetErrorCount() was called.
+   * <p>
+   * This could be useful in the unit tests to validate that no background
+   * errors occurred during a test.  It could also be exposed by the monitoring
+   * framekwork.
+   *
+   * @return the number of errors detected by this class since the error count
+   * was last reset.
+   */
+  public static synchronized long getErrorCount() {
+    return _errorCount;
+  }
+
+
+  /**
+   * Resets the error count to zero.
+   */
+  public static synchronized void resetErrorCount() {
+    _errorCount = 0;
+  }
+
+
+  private static synchronized void incrementErrorCount() {
+    _errorCount++;
+  }
+
+
+  ////////////////////////////////////////////////////////////////////////////
+  //
+  //  PRIVATE
+  //
+  ////////////////////////////////////////////////////////////////////////////
+
+
+  private static String generateLineSpecificErrorMessage(String message) {
+    return message + "  The error occurred at " + getOriginalCallerLineInfo();
+  }
+
+
+  private static void throwNull(String message)
+          throws NullPointerException, AssertionError {
+    String fullMessage = generateLineSpecificErrorMessage(
+            "The specified parameter must not be null. " + message);
+
+    logError(fullMessage);
+
+    // Prefer throwing an assertion if they are enabled.
+    assert false : fullMessage;
+
+    throw new NullPointerException(fullMessage);
+  }
+
+
+
+  private static void logError(String message) {
+    incrementErrorCount();
+
+    String messageWithStack = message + ServerConstants.EOL + getCallingStack();
+
+    // Log to the debug log.
+    debugMessage(DebugLogCategory.CORE_SERVER, DebugLogSeverity.ERROR,
+            CLASS_NAME, "logError", messageWithStack);
+
+    // Log to the error log.
+    org.opends.server.loggers.Error.logError(ErrorLogCategory.CORE_SERVER,
+            ErrorLogSeverity.SEVERE_ERROR,
+            UtilityMessages.MSGID_VALIDATOR_PRECONDITION_NOT_MET,
+            messageWithStack);
+  }
+
+
+  /*
+   * @return a String representation of the line that called the
+   * Validator method.
+   */
+  private static String getOriginalCallerLineInfo() {
+    StackTraceElement stackElements[] = Thread.currentThread().getStackTrace();
+    int callerIndex = getOriginalCallerStackIndex(stackElements);
+    return stackElements[callerIndex].toString();
+  }
+
+
+  /*
+   * @return a stack trace rooted at the line that called the first
+   * Validator method.
+   */
+  private static String getCallingStack() {
+    StackTraceElement stackElements[] = Thread.currentThread().getStackTrace();
+    int callerIndex = getOriginalCallerStackIndex(stackElements);
+
+    StringBuilder buffer = new StringBuilder();
+    for (int i = callerIndex; i < stackElements.length; i++) {
+      StackTraceElement stackElement = stackElements[i];
+      buffer.append(stackElement).append(ServerConstants.EOL);
+    }
+
+    return buffer.toString();
+  }
+
+
+  /*
+   * @return the index in the supplied stack trace of the first non-Validator
+   * method.
+   */
+  private static int getOriginalCallerStackIndex(StackTraceElement stack[]) {
+    // Go up the stack until we find who called the first Validator method.
+    StackTraceElement element = null;
+    int i;
+    for (i = 0; i < stack.length; i++) {
+      element = stack[i];
+      // The stack trace of this thread looks like
+      //   java.lang.Thread.dumpThreads(Native Method)
+      //   java.lang.Thread.getStackTrace(Thread.java:1383)
+      //   org.opends.server.util.Validator.getOriginalCallerLineInfo...
+      //   ...
+      //   original caller  <---- this is what we want to return
+      //   more stack
+      if (!element.getClassName().equals(Validator.class.getName()) &&
+          !element.getClassName().equals(Thread.class.getName())) {
+        break;
+      }
+    }
+
+    return i;
+  }
+}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/util/ValidatorTests.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/util/ValidatorTests.java
new file mode 100644
index 0000000..f4f1e0d
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/util/ValidatorTests.java
@@ -0,0 +1,167 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2006 Sun Microsystems, Inc.
+ */
+package org.opends.server.util;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import static org.testng.Assert.*;
+
+/**
+ * Tests for the Validator class.
+ */
+public class ValidatorTests {
+  private static final Object NON_NULL = new Object();
+
+  //////////////////////////////////////////////////////////////////////////////
+  //
+  //  POSITIVE TESTS
+  //
+  //////////////////////////////////////////////////////////////////////////////
+
+  @Test
+  public void testEnsureNotNull() {
+    boolean returnValue = Validator.ensureNotNull(NON_NULL);
+    assertTrue(returnValue);  // must always return true
+  }
+
+  @Test
+  public void testEnsureNotNull2() {
+    boolean returnValue = Validator.ensureNotNull(NON_NULL, NON_NULL);
+    assertTrue(returnValue);  // must always return true
+  }
+
+  @Test
+  public void testEnsureNotNull3() {
+    boolean returnValue = Validator.ensureNotNull(NON_NULL, NON_NULL, NON_NULL);
+    assertTrue(returnValue);  // must always return true
+  }
+
+  @Test
+  public void testEnsureNotNull4() {
+    boolean returnValue = Validator.ensureNotNull(NON_NULL, NON_NULL, NON_NULL, NON_NULL);
+    assertTrue(returnValue);  // must always return true
+  }
+
+  @Test
+  public void testEnsureTrue() {
+    boolean returnValue = Validator.ensureTrue(true);
+    assertTrue(returnValue);  // must always return true
+  }
+
+  @Test
+  public void testEnsureTrueWithMessage() {
+    boolean returnValue = Validator.ensureTrue(true, "some message");
+    assertTrue(returnValue);  // must always return true
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //
+  //  NEGATIVE TESTS
+  //
+  //////////////////////////////////////////////////////////////////////////////
+
+  @Test(expectedExceptions = {NullPointerException.class, AssertionError.class})
+  public void testEnsureNotNullWithNull() {
+    Validator.ensureNotNull(null);  // Should throw
+  }
+
+
+  @Test(expectedExceptions = {NullPointerException.class, AssertionError.class},
+        dataProvider = "dataEnsureNotNull2WithNull")
+  public void testEnsureNotNull2WithNull(Object param1, Object param2) {
+    Validator.ensureNotNull(param1, param2);  // Should throw
+  }
+
+  @DataProvider(name = "dataEnsureNotNull2WithNull")
+  public Object[][] dataEnsureNotNull2WithNull() {
+    return new Object[][]{
+            {null, NON_NULL},
+            {NON_NULL, null}};
+  }
+
+
+  @Test(expectedExceptions = {NullPointerException.class, AssertionError.class},
+        dataProvider = "dataEnsureNotNull3WithNull")
+  public void testEnsureNotNull3WithNull(Object param1, Object param2, Object param3) {
+    Validator.ensureNotNull(param1, param2, param3);  // Should throw
+  }
+
+  @DataProvider(name = "dataEnsureNotNull3WithNull")
+  public Object[][] dataEnsureNotNull3WithNull() {
+    return new Object[][]{
+            {null, NON_NULL, NON_NULL},
+            {NON_NULL, null, NON_NULL},
+            {NON_NULL, NON_NULL, null}};
+  }
+
+
+  @Test(expectedExceptions = {NullPointerException.class, AssertionError.class},
+        dataProvider = "dataEnsureNotNull4WithNull")
+  public void testEnsureNotNull4WithNull(Object param1, Object param2, Object param3, Object param4) {
+    Validator.ensureNotNull(param1, param2, param3, param4);  // Should throw
+  }
+
+  @DataProvider(name = "dataEnsureNotNull4WithNull")
+  public Object[][] dataEnsureNotNull4WithNull() {
+    return new Object[][]{
+            {null, NON_NULL, NON_NULL, NON_NULL},
+            {NON_NULL, null, NON_NULL, NON_NULL},
+            {NON_NULL, NON_NULL, null, NON_NULL},
+            {NON_NULL, NON_NULL, NON_NULL, null}};
+  }
+
+
+  @Test(expectedExceptions = {RuntimeException.class, AssertionError.class})
+  public void testEnsureTrueWithFalse() {
+    Validator.ensureTrue(false);
+  }
+
+
+  @Test(expectedExceptions = {RuntimeException.class, AssertionError.class})
+  public void testEnsureTrueWithMessageWithFalse() {
+    Validator.ensureTrue(false, "some message");
+  }
+
+
+  @Test
+  public void testMessageContents() {
+    Validator.resetErrorCount();
+    String myMessage = "some test message";
+    String thisMethod = ValidatorTests.class.getName() + "." + "testMessageContents(ValidatorTests.java:";
+    try {
+      Validator.ensureTrue(false, myMessage);
+    } catch (Throwable e) {
+      String caughtMessage = e.getMessage();
+      assertTrue(caughtMessage.indexOf(myMessage) >= 0);
+      assertTrue(caughtMessage.indexOf(thisMethod) >= 0);
+
+      assertEquals(Validator.getErrorCount(), 1);
+      Validator.resetErrorCount();
+      assertEquals(Validator.getErrorCount(), 0);
+    }
+  }
+}

--
Gitblit v1.10.0