Testing exceptions in Scala - scala

I want to test (in Intellij Idea testing framework) the following code:
def eval(t: Term): Term = t match {
case t if isVal(t) => t
case If(t1,t2,t3) if True == eval(t1) => eval(t2)
case If(t1,t2,t3) if False == eval(t1) => eval(t3)
case Succ(t) if isNum(eval(t)) => Succ(eval(t))
case Pred(t) => eval(t) match {
case Zero => Zero
case Succ(v) if isNum(v) => v
case _ => throw TermIsStuck(Pred(eval(t)))
}
case IsZero(t) => eval(t) match {
case Zero => True
case Succ(v) if isNum(v) =>False
case _ => throw TermIsStuck(IsZero(eval(t)))
}
case _ => throw TermIsStuck(t)
}
For a reference you can see this repository. So I wrote the following test:
test("testEval") {
Arithmetic.term(new Arithmetic.lexical.Scanner("if iszero pred pred 2 then if iszero 0 then true else false else false")) match {
case Arithmetic.Success(res,next) => assert(eval(res) == True)
case Arithmetic.Failure(msg,next) => assert(false)
}
Arithmetic.term(new Arithmetic.lexical.Scanner("pred succ succ succ false")) match {
case Arithmetic.Success(res,next) => assert(Arithmetic.eval(res) == TermIsStuck(Succ(False)))
case Arithmetic.Failure(msg,next) => assert(false)
}
}
Getting the error:
Succ(False)
fos.Arithmetic$TermIsStuck: Succ(False) ...
How can I test this catching the error? Indeed this test should be passed...

You are in Scala you are not supposed to throw exception around, but in scalatest you can do something like this:
a[yourException.type] should be thrownBy yourFunction()
You can do a better version of that,
case class Error(exception: Exception){
throw exception
???
}
Or something like
case object Error
And then you check it like:
Error shouldBe yourFunction()

Looks like you're not using any widespread testing framework for scala (such as scalatest or specs2) - an obvious recommendation would be to use some.
However, if you'd like to stick with "no-framework" approach, one option would be to use good old try .. catch:
val term = Arithmetic.term(
new Arithmetic.lexical.Scanner("pred succ succ succ false")
)
try {
val evaluated = term match {
case Arithmetic.Success(res,next) => Arithmetic.eval(res)
case Arithmetic.Failure(msg,next) => assert(false)
}
} catch {
case TermIsStuck(Succ(False)) => // do nothing, or explicitly mark test as successful
case _ => assert(false) // any other exception should fail the test
}
However, I think the implementation is partially broken - it never returns Arithmetic.Failure, but throws exception. I think the intent of Arithmetic.Failure was exactly to capture such cases. If that's the case, then better implementation would be to replace throw TermIsStuck with Arithmetic.Failure(TermIsStuck(...)).

Related

Scala - Return value from an anonymous function

I've a named function that as an Either[A, List[B]] as return type. Inside that named function, I have a anonymous function that I'd like to make it return a value to the named function. Instead I keep getting the error "Non local returns are no longer supported; use scala.util.control.NonLocalReturns instead".
I did some research but wasn't able to find a solution.
Am I missing something? Is there any to workaround this problem?
Here's my code
def readEvents(SchedulingNode: Node): Either[Error, List[Event]] =
val events: List[Either[Error, Event]] = SchedulingNode.child
.filter(n => n.label == EVENT_NODE_NAME)
.map(n => {
val head: Head = n.attribute(HEAD_ATTRIBUTE) match {
case None => return Left(EmptyProperty("head")) //Error occurs here
case Some(s) => Head.from(s.toString()) match
case Left(e: Error) => return Left(e); //Here also
case Right(h: Head) => h
}
Event.from(head, 1) match {
case Left(e: Error) => Left(e);
case Right(ev: Event) => Right(ev)
}
}).toList
//Rest of the code...

How to put error logs in code when using pattern matching?

I have a function convert date time to epoch, and I want to put some logs where it failed. Such as case _ => and .getOrElse(JNothing) , how can I do that?
def time_to_epoch(params: List[JValue]): JValue = params match {
case JString(timestamp) :: JString(pattern) :: JString(timezone) :: Nil =>
Try {
***
}.getOrElse(JNothing) // for saying something similar to can't convert time to epoch
case _ =>
JNothing // Add a (ErrorMessage(xxxxxxx)) for saying number of parameters are invalid and what are expected inline function forma
}
def time_to_epoch(params: List[JValue]): JValue = params match {
case JString(timestamp) :: JString(pattern) :: JString(timezone) :: Nil =>
Try {
//***
}.getOrElse {
log.error("Cant ...")
JNothing
}
case _ =>
log.error("Number ...")
JNothing
}
For functional programming solution, there's treelog you can use, but it's really not necessary in your case, unless you need the function to be strictly pure.
If time_to_epoch can fail then it is better to return a Try rather than a special failure value like JNothing.
case class MyException(msg: String) extends Exception
def time_to_epoch(params: List[JValue]): Try[JValue] = params match {
case JString(timestamp) :: JString(pattern) :: JString(timezone) :: Nil =>
Try {
???
}
case _ =>
Failure(MyException("Invalid parameters"))
}
You can print the error information using match:
time_to_epoch(???) match {
case Failure(e) =>
println(s"Operation failed: $e")
case _ =>
}
The advantage of this is that it is easy to chain multiple Try operations without having to test for failure at each step. It allows the code to focus on the main code path while still handling errors correctly.

What can i use to write this scala code better?

functionThatReturnsATry[Boolean]() match {
case Success(value) =>
value match {
case true => somethingThatReturnsFuture[Unit]
case false =>
Failure(new SomeException("This failed here"))
}
case Failure(exception) => Failure(exception)
}
The code will return Future[Unit] when functionThatReturnsATry finishes succesfully and returns true.
If functionThatReturnsATry fails, i want to pass that failure up the chain.
If functionThatReturnsATry returns false, i want to pass a new sepecific failure up the chain
One improvement would be to use guard expressions on the match to separate the three different cases. You should also return Future.failed rather than Failure so that the result is Future[Unit] not Any:
functionThatReturnsATry[Boolean]() match {
case Success(value) if value =>
somethingThatReturnsFuture[Unit]
case Success(_) =>
Future.failed(new SomeException("This failed here"))
case Failure(exception) =>
Future.failed(exception)
}
I like the existing answer, but as an alternative, if you don't care about controlling the precise exception of the first step, you can wrap your Try in a Future and use a for-comprehension:
def attempt(): Try[Boolean] = Success(true)
def soon(): Future[Unit] = Future.failed(new RuntimeException("uh"))
for {
success <- Future.fromTry(attempt()) if success
result <- soon()
} yield result
The code is available here on Scastie.
I'd be tempted to fold() over the Try.
functionThatReturnsATryBool()
.fold(Future.failed
,if (_) somethingThatReturnsFutureUnit()
else Future.failed(new SomeException("This failed here"))
)
The result is type Future[Unit] with either type of failure returned as Future(Failure(java.lang.Exception(...))). No loss of error message.
functionThatReturnsATry[Boolean]() match {
case Success(true) => somethingThatReturnsFuture[Unit]
case Success(false) => Future.failed(new SomeException("This failed here"))
case Failure(exception) => Future.failed(exception)
}
https://scalafiddle.io/sf/DSaGvul/0

What is the proper way to return from an exception in Scala?

In a non-functional language, I might do something like:
try {
// some stuff
} catch Exception ex {
return false;
}
// Do more stuff
return true;
In Scala, however, this pattern is clearly not correct. If my scala code looks like this:
try {
// do some stuff
}
catch {
case e: Exception => // I want to get out of here and return false
)
}
// do more stuff
true
How do I properly do that? I don't want to use the "return" statement, of course, but I also don't want to drop through and "do more stuff" and eventually return true.
You want to represent a computation that can either succeed or signal that an error has occurred. That's the perfect use case for the Try monad.
import scala.util.{ Try, Success, Failure }
def myMethod: Try[Something] = Try {
// do stuff
// do more stuff
// if any exception occurs here, it gets wrapped into a Failure(e)
}
So you're returning a Try instead of a Bool, which is infinitely more clear and idiomatic.
Usage example:
myMethod match {
case Success(x) => println(s"computation succeded with result $x")
case Failure(e) => println(s"computation failed with exception $e.getMessage")
}
If you don't even care about the exception, but you just want to return a value in case of success, you can even convert the Try to an Option.
def myMethod: Option[Something] = Try {
// do stuff
// do more stuff
// return something
// if any exception occurs here, it gets wrapped into a Failure(e)
}.toOption
myMethod match {
case Some(x) => println(s"computation succeded with result $x")
case None => println("computation failed")
}
To respond to the question in the comments, you can do
Try {
// do stuff
} match {
case Failure(_) => false
case Success(_) =>
// do more stuff
// true
}
although I would suggest to return something more meaningful than a Boolean, whenever it makes sense.
Of course this can be nested
Try {
// do stuff
} match {
case Failure(_) => false
case Success(_) =>
// do more stuff
Try {
// something that can throw
} match {
case Failure(_) => false
case Success(_) =>
// do more stuff
true
}
}
but you should consider putting the Try chunks into separate functions (returning a Try).
Ultimately, we can take advantage of the fact that Try is a monad, and do something like this
Try { /* java code */ }.flatMap { _ =>
// do more stuff
Try { /* java code */ }.flatMap { _ =>
// do more stuff
Try { /* java code */ }
}
} match {
case Failure(_) => false // in case any of the Try blocks has thrown an Exception
case Success(_) => true // everything went smooth
}
scala> def f() = try { ??? ; 1 } catch { case _: Throwable => 2 }
f: ()Int
scala> f()
res2: Int = 2
scala> import util._
import util._
scala> def g() = Try { ??? ; 1 } recover { case _ => 2 } get
warning: there was one feature warning; re-run with -feature for details
g: ()Int
scala> g()
res3: Int = 2
HTH. Small functions helps.
Another hint:
scala> def j() = Try (1) map (_ + 42) recover { case _ => 2 } get
warning: there was one feature warning; re-run with -feature for details
j: ()Int
scala> j()
res4: Int = 43
try-catch expression is not good for functional programming.
Anyway, an easy solution that still uses try-catch:
val result = try {
// do some stuff
Some(/* The final expression */)
}
catch {
case e: Exception => // Do something or nothing
None
}
result match {
case Some(r) => // Do something with r
true
case None => false
}
You can use scala.util.Try for cleaner and more functional-styled code.
Refer to https://codereview.stackexchange.com/questions/38689/code-with-many-early-returns-exits-into-the-functional-style
I faced a similar problem like you, but the answer in the Stackexchange CodeReview helped me a lot.
Successful or erroneous cases can be represented by several Scala type.
If you consider the error in the meaning of "something is missing" (e.g. file not found), you can use Option[T] (e.g. Option[File]), with case values None or Some(T). Then orElse, getOrElse or fold and map/flatMap functions can be used to dispatch cased.
You can also use Either[E, T], with (by convention), in Left(E) case the error value (e.g. a String as error message), and in Right(T) successful T value.
Monads Try[T] or Future[T] can be used in the same way.
In the field of I/O, the very nice scala-arm lib provide type ManagedResource[T] that wrap either successful (T) or erroneous (List[Throwable]]) result of computation based on resources.
Valudation types in Scalaz are also useful for such cases.
'util.Try{ do some stuff }.isSuccess'

Is there a full specification for pattern matching possibilities of Scala?

Is there a full specification for pattern matching possibilities of Scala?
I am unable to fix following code:
something match {
case e # (sae: ServerApiException if sae.statusCode == 401 | _: UnauthorizedException) => {
doSomething(e)
}
...
}
(It does not compile in 2.8.1.)
I'm not sure I'd write the code this way; it's hard to follow (in addition to not working in its original form).
I'd rather go for something like
def doSomething(e: Exception) = { /* whatever */ }
something match {
case sae: ServerApiException if (sae.statusCode == 401) => doSomething(sae)
case ue: UnauthorizedException => doSomething(ue)
}
to avoid duplicate code. Or you could use options:
(something match {
case sae: ServerApiException if (sae.statusCode == 401) => Some(sae)
case ue: UnauthorizedException => Some(ue)
case _ => None
}).foreach(e => /* do something */ )
if you prefer to write the method afterwards. But I think the first way is likely the clearest.
Chapter 8 of the Scala Language Spec? (pdf).
More concretely, this answer may be of some assistance, that is you should be able to do something like:
case e: Exception if e.isInstanceOf[UnauthorizedException] || (e.isInstanceOf[ServerApiException] && e.asInstanceOf[ServerApiException].statusCode == 401) => {
doSomething(e)
}
Finally, I managed that with help of Scala Language Spec (Scala Syntax Summary):
something match {
case e: Exception if (e match {
case sae: ServerApiException if sae.statusCode == 401 => true
case _: UnauthorizedException => true
case _ => false
}) => {
doSomething(e)
}
...
}