org.specs.matcher.PatternMatchers.scala Maven / Gradle / Ivy
/**
* Copyright (c) 2007-2009 Eric Torreborre
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software. Neither the name of specs nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written permission.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package org.specs.matcher
import org.specs.matcher.MatcherUtils._
import org.specs.specification.Result
/**
* The PatternMatchers
trait provides matchers which allow to use pattern matching
* to match expressions.
*/
trait PatternMatchers extends PatternBaseMatchers with PatternBeHaveMatchers
trait PatternBaseMatchers {
/**
* Matches if the value v
is like the pattern { case expression => boolean }
* It uses the fact that we can use the following syntax to map Options:
* myOption.map { case expression => boolean }
* In that case, the pattern parameter would be { case expression => boolean }
, a function of type Any => Boolean
* The Sugar
object can be used to get a shorter expression by having the ok
alias for true
:
*
-
List(1, 2) must beLike { case x::y::Nil => ok }
*
* @param pattern a case expression
* @return false if there is no match
* @return the value inside the mapped option if there is a match, which should be true
*/
def beLike[T](pattern: => PartialFunction[T, Boolean]) = new Matcher[T]() {
def apply(v: => T) = {
val value = v
(if (value == null || !pattern.isDefinedAt(value))
false
else
pattern.apply(value)
,
d(value) + " matches the given pattern",
d(value) + " doesn't match the expected pattern")
}
}
/**
* Alias for beLike
*/
def beLikeA[T](pattern: => PartialFunction[T, Boolean]) = beLike(pattern)
/**
* Matches if the value v
is None
*/
def beNone = new Matcher[Option[Any]]() {
def apply(v: => Option[Any]) = {
val value = v
val none: Option[Any] = None
(value match {
case n if (n == none) => true
case _ => false
},
d(value) + " is None",
d(value) + " is not None")
}
}
/**
* @deprecated use beAsNoneAs
*/
def beAlsoNone[T](a: =>Option[T]) = beAsNoneAs(a)
/**
* Matches if a is None when v is None and a is not None when v is not None
*/
def beAsNoneAs[T](a: =>Option[T]) = new Matcher[Option[T]]() {
def apply(v: =>Option[T]) = {
val x = a;
val y = v;
(x == None && y == None || x != None && y != None, "both values are None",
if (x == None) d(y) + " is not None" else d(x) + " is not None")
}
}
/**
* Matches if the value v
is Some(x)
*/
def beSome[T] = new CaseMatcher[T]() {
def someApply(v: => Option[T]) = {
val value = v
(value match {
case Some(x) => true
case _ => false
},
d(value) + " is Some(x)",
d(value) + " is not Some(x)")
}
}
/**
* Matches if the value v
is Some(x)
*/
def beSome[T](expected: T) = new CaseMatcher[T]() {
def someApply(v: => Option[T]) = {
val value = v
(value match {
case Some(`expected`) => true
case _ => false
},
d(value) + " is " + q("Some("+expected+")"),
d(value) + " is not " + q("Some("+expected+")"))
}
}
/**
* Alias for beSome[Any]
*/
def beSomething = beSome[Any]
/**
* The CaseMatcher class allow to verify expressions such as:
* Some(x) must beSome[String].which(_.startWith("abc"))
*/
abstract class CaseMatcher[T] extends Matcher[Option[T]] {
private var whichFunction: Option[T => Boolean] = None
def someApply(value: => Option[T]): (Boolean, String, String)
def which(g: T => Boolean) = {
whichFunction = Some(g)
this
}
override def apply(a: => Option[T]) =
if (whichFunction == Some(null))
(false, "the 'which' property is a not a null function", "the 'which' property is a null function")
else
whichFunction match {
case None => someApply(a)
case Some(g) => ( a match {
case Some(x) => g(x)
case _ => false
},
description.getOrElse("there") + " is a Some(x) verifying the given property",
description.getOrElse("there") + " is no Some(x) verifying the given property")
}
}
}
trait PatternBeHaveMatchers { outer: PatternBaseMatchers =>
/**
* matcher aliases and implicits to use with BeVerb and HaveVerb
*/
implicit def toPatternResult[T](result: Result[T]) = new PatternResultMatcher(result)
class PatternResultMatcher[T](result: Result[T]) {
def like(pattern: => PartialFunction[T, Boolean]) = result.matchWithMatcher(beLike(pattern))
}
implicit def toOptionPatternResult[T](result: Result[Option[T]]) = new OptionResultMatcher(result)
class OptionResultMatcher[T](result: Result[Option[T]]) {
def asNoneAs(a: =>Option[T]) = result.matchWithMatcher(beAsNoneAs(a))
def beNone = result.matchWithMatcher(outer.beNone)
def none = result.matchWithMatcher(outer.beNone)
def beSome = result.matchWithMatcher(outer.beSome)
def some = result.matchWithMatcher(outer.beSome)
}
implicit def toSomePatternResult[T](result: Result[Some[T]]) = new SomeResultMatcher(result)
class SomeResultMatcher[T](result: Result[Some[T]]) {
def asNoneAs(a: =>Some[T]) = result.matchWithMatcher(beAsNoneAs(a))
def beNone = result.matchWithMatcher(outer.beNone)
def none = result.matchWithMatcher(outer.beNone)
def beSome = result.matchWithMatcher(outer.beSome)
def some = result.matchWithMatcher(outer.beSome)
}
def like[T](pattern: => PartialFunction[T, Boolean]) = beLike(pattern)
def asNoneAs[T](a: =>Option[T]) = beAsNoneAs(a)
def none = beNone
def some = beSome
}
/**
* Companion object for PatternMatchers.
*/
object PatternMatchers extends PatternMatchers
© 2015 - 2025 Weber Informatics LLC | Privacy Policy