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

org.scalautils.EqualityConstraints.scala Maven / Gradle / Ivy

Go to download

ScalaTest is a free, open-source testing toolkit for Scala and Java programmers.

The 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.scalautils

/**
 * Trait that defines abstract methods used to enforce compile-time type constraints for equality comparisons, and defines === and !== operators
 * used by matchers.
 *
 * 

* This abstract methods of this trait are selectively implemented as implicit by subclasses to enable a spectrum of type constraints for the * === and !== operators. As an illustration, if in the expression, a === b, the type of a * is A and b is B, the following three levels of compile-time checking can be obtained from * EqualityConstraints subtraits: *

* *

* Unchecked - A and B can be any two types. This (weakest) constraint level is available from * subtraits TripleEquals and LegacyTripleEquals. *

* *

* Conversion checked - A must be a subtype of B, or vice versa, or an implicit conversion must be available that converts * A to B, or vice versa. (Both A and B can be the same type, because a type is considered a subtype * of itself.) * This (intermediate) constraint level is available from subtraits ConversionCheckedTripleEquals and ConversionCheckedLegacyTripleEquals. *

* *

* Type checked - A must be a subtype of B, or vice versa. * (Both A and B can be the same type, because a type is considered a subtype * of itself.) * This (strongest) constraint level is available from subtraits TypeCheckedTripleEquals and TypeCheckedLegacyTripleEquals. *

* *

* The difference between the regular and “legacy” variants of each pair of traits is that the === and !== operators * provided by the regular variants result in Boolean, whereas those of the legacy variants result in Option[String]. For example, were you * to mix in TripleEquals, the expression 1 + 1 === 3 would return false. Were you to mix in LegacyTripleEquals, * by contrast, the expression 1 + 1 === 3 would return Some("2 did not equal 3"). *

* *

* The purpose of the legacy variants is to maintain compatibility with * existing code that uses ScalaTest's original === defined in trait org.scalatest.Assertions. This * === operator returned an * Option[String] to facilitate better error messages. With the advent of macros in Scala 2.10, it is possible to obtain good error messages by making * assert a macro. Once ScalaTest no longer supports Scala 2.9, the legacy variants (LegacyTripleEquals, * ConversionCheckedLegacyTripleEquals, and TypeCheckedLegacyTripleEquals) will be deprecated and eventually removed, === will * return only Boolean, and good error * messages will be obtained via macros. *

* *

* This trait defines all methods that need to be defined implicitly by the six subtraits so that if multiple subtraits are used together, the inner-most * subtrait in scope can not only enable the implicits it needs by overriding or hiding those methods (currently-in-scope as regular, non-implicit methods) and making * them implicit, it can also disable any implicits enabled by its sibling subtraits in enclosing scopes. For example, if your test class mixes * in TypeCheckedTripleEquals, inside your test class the following methods will be implicit: *

* *
    *
  • convertToCheckingEqualize
  • *
  • typeCheckedEqualityConstraint
  • *
  • lowPriorityTypeCheckedEqualityConstraint
  • *
* *

* If in the body of a test you want to turn off the type checking, you can import the members * of TripleEquals in the body of that test. This will not only hide * non-implicit methods convertToEqualizer unconstrainedEquality of TypeCheckedTripleEquals, * replacing those with implicit ones defined in TripleEquals, it will also hide the three methods made implicit in TypeCheckedTripleEquals * (and listed above), replacing them by non-implicit ones. *

* *

* In short, you should be able to select a primary constraint level via either a mixin or import, then change that in nested scopes * however you want, again either through a mixin or import, without getting any implicit conversion ambiguity. The innermost constraint level in scope * will always be in force. *

* * @author Bill Venners */ trait EqualityConstraints { /** * Return an Equality[A] for any type A that determines equality via the == operator on type A. * * @return a DefaultEquality for type A */ def defaultEquality[A]: Equality[A] /** * Convert to an Equalizer that provides === and !== operators that * result in Boolean and enforce no type constraint. * *

* This method is overridden and made implicit by subtrait TripleEquals and overriden as non-implicit by the other subtraits in this package. *

* * @param left the object whose type to convert to Equalizer. * @throws NullPointerException if left is null. */ def convertToEqualizer[T](left: T): Equalizer[T] /** * Convert to a LegacyEqualizer that provides === and !== operators that * result in Option[String] and enforce no type constraint. * *

* This method is overridden and made implicit by subtrait LegacyTripleEquals and overriden as non-implicit by the other subtraits in this package. *

* * @param left the object whose type to convert to LegacyEqualizer. * @throws NullPointerException if left is null. */ def convertToLegacyEqualizer[T](left: T): LegacyEqualizer[T] /** * Convert to an CheckingEqualizer that provides === and !== operators that result in Boolean and enforce a type constraint. * *

* This method is overridden and made implicit by subtraits TypeCheckedTripleEquals and ConversionCheckedTripleEquals, and overriden as * non-implicit by the other subtraits in this package. *

* * @param left the object whose type to convert to CheckingEqualizer. * @throws NullPointerException if left is null. */ def convertToCheckingEqualizer[T](left: T): CheckingEqualizer[T] /** * Convert to a LegacyCheckingEqualizer that provides === and !== operators that result in Option[String] and * enforce a type constraint. * *

* This method is overridden and made implicit by subtraits TypeCheckedLegacyTripleEquals and ConversionCheckedLegacyTripleEquals, and * overriden as non-implicit by the other subtraits in this package. *

* * @param left the object whose type to convert to LegacyCheckingEqualizer. * @throws NullPointerException if left is null. */ def convertToLegacyCheckingEqualizer[T](left: T): LegacyCheckingEqualizer[T] /** * Provides an EqualityConstraint[A, B] class for any two types A and B, with no type constraint enforced, given an * implicit Equality[A]. * *

* The implicitly passed Equality[A] must be used to determine equality by the returned EqualityConstraint's * areEqual method. *

* *

* This method is overridden and made implicit by subtraits TripleEquals and LegacyTripleEquals, and * overriden as non-implicit by the other subtraits in this package. *

* * @param equalityOfA an Equality[A] type class to which the EqualityConstraint.areEqual method will delegate to determine equality. * @return an EqualityConstraint[A, B] whose areEqual method delegates to the areEqual method of * the passed Equality[A]. */ def unconstrainedEquality[A, B](implicit equalityOfA: Equality[A]): EqualityConstraint[A, B] /** * Provides an EqualityConstraint[A, B] class for any two types A and B, enforcing the type constraint that A must be a subtype of B, given an implicit Equality[A]. * *

* The implicitly passed Equality[A] must be used to determine equality by the returned EqualityConstraint's * areEqual method. *

* *

* This method is overridden and made implicit by subtraits * LowPriorityTypeCheckedConstraint (extended by * TypeCheckedTripleEquals), and * LowPriorityTypeCheckedLegacyConstraint (extended by * TypeCheckedLegacyTripleEquals), and * overriden as non-implicit by the other subtraits in this package. *

* * @param equalityOfA an Equality[A] type class to which the EqualityConstraint.areEqual method * will delegate to determine equality. * @param ev evidence that A is a subype of
B * @return an EqualityConstraint[A, B] whose areEqual method delegates to the * areEqual method of the passed Equality[A]. */ def lowPriorityTypeCheckedEqualityConstraint[A, B](implicit equalityOfA: Equality[A], ev: A <:< B): EqualityConstraint[A, B] /** * Provides an EqualityConstraint[A, B] class for any two types A and B, enforcing the type constraint that B must be a subtype of A, given an implicit Equality[A]. * *

* The implicitly passed Equality[A] must be used to determine equality by the returned EqualityConstraint's * areEqual method. *

* *

* This method is overridden and made implicit by subtraits * TypeCheckedTripleEquals) and * TypeCheckedLegacyTripleEquals, and * overriden as non-implicit by the other subtraits in this package. *

* * @param equalityOfA an Equality[A] type class to which the EqualityConstraint.areEqual method will delegate to determine equality. * @param ev evidence that B is a subype of A * @return an EqualityConstraint[A, B] whose areEqual method delegates to the areEqual method of * the passed Equality[A]. */ def typeCheckedEqualityConstraint[A, B](implicit equalityOfA: Equality[A], ev: B <:< A): EqualityConstraint[A, B] /** * Provides an EqualityConstraint[A, B] class for any two types A and B, enforcing the type constraint that A is implicitly convertible to B, given an implicit Equality[A]. * *

* The implicitly passed Equality[A] must be used to determine equality by the returned EqualityConstraint's * areEqual method. *

* *

* This method is overridden and made implicit by subtraits * LowPriorityConversionCheckedConstraint (extended by * ConversionCheckedTripleEquals), and * LowPriorityConversionCheckedLegacyConstraint (extended by * ConversionCheckedLegacyTripleEquals), and * overriden as non-implicit by the other subtraits in this package. *

* * @param equalityOfA an Equality[A] type class to which the EqualityConstraint.areEqual method will delegate to determine equality. * @param cnv an implicit conversion from A to B * @return an EqualityConstraint[A, B] whose areEqual method delegates to the areEqual method of * the passed Equality[A]. */ def lowPriorityConversionCheckedEqualityConstraint[A, B](implicit equalityOfB: Equality[B], cnv: A => B): EqualityConstraint[A, B] /** * Provides an EqualityConstraint[A, B] class for any two types A and B, enforcing the type constraint that B is implicitly convertible to A, given an implicit Equality[A]. * *

* The implicitly passed Equality[A] must be used to determine equality by the returned EqualityConstraint's * areEqual method. *

* *

* This method is overridden and made implicit by subtraits * ConversionCheckedTripleEquals) and * ConversionCheckedLegacyTripleEquals, and * overriden as non-implicit by the other subtraits in this package. *

* * @param equalityOfA an Equality[A] type class to which the EqualityConstraint.areEqual method will delegate to determine equality. * @param cnv an implicit conversion from B to A * @return an EqualityConstraint[A, B] whose areEqual method delegates to the areEqual method of * the passed Equality[A]. */ def conversionCheckedEqualityConstraint[A, B](implicit equalityOfA: Equality[A], cnv: B => A): EqualityConstraint[A, B] /** * Returns a TripleEqualsInvocation[T], given an object of type T, to facilitate * the “<left> should === <right>” syntax * of Matchers. * * @param right the right-hand side value for an equality assertion * @return a TripleEqualsInvocation wrapping the passed right value, with expectingEqual * set to true. */ def ===[T](right: T): TripleEqualsInvocation[T] = new TripleEqualsInvocation[T](right, true) /** * Returns a TripleEqualsInvocation[T], given an object of type T, to facilitate * the “<left> should !== <right>” syntax * of Matchers. * * @param right the right-hand side value for an equality assertion * @return a TripleEqualsInvocation wrapping the passed right value, with expectingEqual * set to false. */ def !==[T](right: T): TripleEqualsInvocation[T] = new TripleEqualsInvocation[T](right, false) /** * Returns a TripleEqualsInvocation[Null], given a null reference, to facilitate * the “<left> should === null” syntax * of Matchers. * * @param right a null reference * @return a TripleEqualsInvocation wrapping the passed null value, with expectingEqual * set to true. */ def ===(right: Null): TripleEqualsInvocation[Null] = new TripleEqualsInvocation[Null](right, true) /** * Returns a TripleEqualsInvocation[Null], given a null reference, to facilitate * the “<left> should !== null” syntax * of Matchers. * * @param right a null reference * @return a TripleEqualsInvocation wrapping the passed null value, with expectingEqual * set to false. */ def !==(right: Null): TripleEqualsInvocation[Null] = new TripleEqualsInvocation[Null](right, false) /** * Returns a TripleEqualsInvocationOnInterval[T], given an Interval[T], to facilitate * the “<left> should === (<pivot> +- <tolerance>)” * syntax of Matchers. * * @param right the Interval[T] against which to compare the left-hand value * @return a TripleEqualsInvocationOnInterval wrapping the passed Interval[T] value, with * expectingEqual set to true. */ def ===[T](right: Interval[T]): TripleEqualsInvocationOnInterval[T] = new TripleEqualsInvocationOnInterval[T](right, true) /** * Returns a TripleEqualsInvocationOnInterval[T], given an Interval[T], to facilitate * the “<left> should !== (<pivot> +- <tolerance>)” * syntax of Matchers. * * @param right the Interval[T] against which to compare the left-hand value * @return a TripleEqualsInvocationOnInterval wrapping the passed Interval[T] value, with * expectingEqual set to false. */ def !==[T](right: Interval[T]): TripleEqualsInvocationOnInterval[T] = new TripleEqualsInvocationOnInterval[T](right, false) }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy