All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scalatest.exceptions.StackDepthException.scala Maven / Gradle / Ivy

There is a newer version: 3.0.0-RC3
Show newest version
/*
 * Copyright 2001-2013 Artima, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.scalatest.exceptions

import org.scalactic.Requirements._
import org.scalactic.exceptions.NullArgumentException

/**
 * Exception class that encapsulates information about the stack depth at which the line of code that failed resides,
 * so that information can be presented to the user that makes it quick to find the failing line of code. (In other
 * words, the user need not scan through the stack trace to find the correct filename and line number of the problem code.)
 * Having a stack depth is more useful in a testing environment in which test failures are implemented as
 * thrown exceptions, as is the case in ScalaTest's built-in suite traits.
 *
 * @param messageFun a function that produces an optional detail message for this StackDepthException.
 * @param cause an optional cause, the Throwable that caused this StackDepthException to be thrown.
 * @param failedCodeStackDepthFun a function that produces the depth in the stack trace of this exception at which the line of test code that failed resides.
 *
 * @throws NullArgumentException if either messageFun, cause or failedCodeStackDepthFun is null, or Some(null).
 *
 * @author Bill Venners
 */
abstract class StackDepthException(
  val messageFun: StackDepthException => Option[String],
  val cause: Option[Throwable],
  val failedCodeStackDepthFun: StackDepthException => Int
) extends RuntimeException(if (cause != null && cause.isDefined) cause.get else null) with StackDepth {

  requireNonNull(messageFun, cause, failedCodeStackDepthFun)

  cause match {
    case Some(null) => throw new NullArgumentException("cause was a Some(null)")
    case _ =>
  }

  /**
   * Constructs a StackDepthException with an optional pre-determined message, optional cause, and
   * a failedCodeStackDepth function.
   *
   * @param message an optional detail message for this StackDepthException.
   * @param cause an optional cause, the Throwable that caused this StackDepthException to be thrown.
   * @param failedCodeStackDepthFun a function that return the depth in the stack trace of this exception at which the line of test code that failed resides.
   *
   * @throws NullArgumentException if either message or cause is null or Some(null), or failedCodeStackDepthFun is null.
   */
  def this(message: Option[String], cause: Option[Throwable], failedCodeStackDepthFun: StackDepthException => Int) =
    this(
      message match {
        case null => throw new NullArgumentException("message was null")
        case Some(null) => throw new NullArgumentException("message was a Some(null)")
        case _ => (e: StackDepthException) => message
      },
      cause,
      failedCodeStackDepthFun
    )

  /**
   * Constructs a StackDepthException with an optional pre-determined message,
   * optional cause, and and failedCodeStackDepth. (This was
   * the primary constructor form prior to ScalaTest 1.5.)
   *
   * @param message an optional detail message for this StackDepthException.
   * @param cause an optional cause, the Throwable that caused this StackDepthException to be thrown.
   * @param failedCodeStackDepth the depth in the stack trace of this exception at which the line of test code that failed resides.
   *
   * @throws NullArgumentException if either message of cause is null, or Some(null).
   */
  def this(message: Option[String], cause: Option[Throwable], failedCodeStackDepth: Int) =
    this(
      message match {
        case null => throw new NullArgumentException("message was null")
        case Some(null) => throw new NullArgumentException("message was a Some(null)")
        case _ => (e: StackDepthException) => message
      },
      cause,
      (e: StackDepthException) => failedCodeStackDepth
    )

  /**
   * An optional detail message for this StackDepth exception.
   *
   * 

* One reason this is lazy is to delay any searching of the stack trace until it is actually needed. It will * usually be needed, but not always. For example, exceptions thrown during a shrink phase of a failed property * will often be StackDepthExceptions, but whose message will never be used. Another related reason is to remove the need * to create a different exception before creating this one just for the purpose of searching through its stack * trace for the proper stack depth. Still one more reason is to allow the message to contain information about the * stack depth, such as the failed file name and line number. *

*/ lazy val message: Option[String] = messageFun(this) /** * The depth in the stack trace of this exception at which the line of test code that failed resides. * *

* One reason this is lazy is to delay any searching of the stack trace until it is actually needed. It will * usually be needed, but not always. For example, exceptions thrown during a shrink phase of a failed property * will often be StackDepthExceptions, but whose failedCodeStackDepth will never be used. Another reason is to remove the need * to create a different exception before creating this one just for the purpose of searching through its stack * trace for the proper stack depth. Still one more reason is to allow the message to contain information about the * stack depth, such as the failed file name and line number. *

*/ lazy val failedCodeStackDepth: Int = failedCodeStackDepthFun(this) /** * Returns the detail message string of this StackDepthException. * * @return the detail message string of this StackDepthException instance (which may be null). */ override def getMessage: String = message.orNull /* * Throws IllegalStateException, because StackDepthExceptions are * always initialized with a cause passed to the constructor of superclass RuntimeException. */ override final def initCause(throwable: Throwable): Throwable = { throw new IllegalStateException } /** * Indicates whether this object can be equal to the passed object. */ def canEqual(other: Any): Boolean = other.isInstanceOf[StackDepthException] /** * Indicates whether this object is equal to the passed object. If the passed object is * a StackDepthException, equality requires equal message, * cause, and failedCodeStackDepth fields, as well as equal * return values of getStackTrace. */ override def equals(other: Any): Boolean = other match { case that: StackDepthException => (that canEqual this) && message == that.message && cause == that.cause && failedCodeStackDepth == that.failedCodeStackDepth && getStackTrace.deep == that.getStackTrace.deep case _ => false } /** * Returns a hash code value for this object. */ override def hashCode: Int = 41 * ( 41 * ( 41 * ( 41 + message.hashCode ) + cause.hashCode ) + failedCodeStackDepth.hashCode ) + getStackTrace.hashCode } private[scalatest] object StackDepthException { /** * If message or message contents are null, throw a null exception, otherwise * create a function that returns the option. */ def toExceptionFunction(message: Option[String]): StackDepthException => Option[String] = { message match { case null => throw new NullArgumentException("message was null") case Some(null) => throw new NullArgumentException("message was a Some(null)") case _ => { e => message } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy