Identify exact failed match from failed Scalacheck property in specs2 - scala

I am running a specs2 test suite from sbt, using the test command. When a ScalaCheck property fails, I just get to see the filename and line number in my code where the specs2 match fails - which is not very useful when that happens to be a utility method which does a common type of check that I am frequently doing. A stack trace would be better.
I've tried the last command in sbt, but that doesn't display the stack trace I'm looking for. The only stack trace last displays is this generic one:
java.lang.RuntimeException: Tests unsuccessful
at scala.sys.package$.error(package.scala:27)
at scala.Predef$.error(Predef.scala:66)
at sbt.Tests$.showResults(Tests.scala:168)
at sbt.Defaults$$anonfun$testTasks$5.apply(Defaults.scala:279)
at sbt.Defaults$$anonfun$testTasks$5.apply(Defaults.scala:279)
at sbt.Scoped$$anonfun$hf2$1.apply(Structure.scala:473)
at sbt.Scoped$$anonfun$hf2$1.apply(Structure.scala:473)
at scala.Function1$$anonfun$compose$1.apply(Function1.scala:41)
at sbt.Scoped$Reduced$$anonfun$combine$1$$anonfun$apply$11.apply(Structure.scala:295)
at sbt.Scoped$Reduced$$anonfun$combine$1$$anonfun$apply$11.apply(Structure.scala:295)
at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:40)
at sbt.std.Transform$$anon$5.work(System.scala:67)
at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:221)
at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:221)
at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18)
at sbt.Execute.work(Execute.scala:227)
at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:221)
at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:221)
at sbt.CompletionService$$anon$1$$anon$2.call(CompletionService.scala:26)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
I also have FINEST logging level enabled in the java.util.logging properties file.
For now I am working around this issue using the Eclipse debugger, but that's unnecessarily heavyweight in some cases.

You can display the stacktrace failures by passing the failtrace argument on the command line. This is documented in the Arguments part of the User Guide.
Also you have to know that this stacktrace is filtered to avoid showing specs2's own stack so if you want to see everything you need to add fullstacktrace which is a shortcut for a TraceFilter that filters nothing.

I decided to take a different approach to identifying the failed match - using aka, like this:
def occurExactlyOnceInBody = be_===(1) ^^ { (s: String) => body.tails.count(_.startsWith(s)) aka "No. of occurences of " + s + " in body" }
The downside is this does need to be applied manually, but the upside is it's easier to understand the failures.

Related

Errors while using VS Code extension

I try to use the VS Code extension for Isabelle 2019. When I try to open the Isabelle output I get the exception
Exception in thread "event_timer" java.util.NoSuchElementException: key not found: IsabelleDejaVuSans.ttf
at scala.collection.MapLike.default(MapLike.scala:231)
at scala.collection.MapLike.default$(MapLike.scala:230)
at scala.collection.AbstractMap.default(Map.scala:59)
at scala.collection.MapLike.apply(MapLike.scala:140)
at scala.collection.MapLike.apply$(MapLike.scala:139)
at scala.collection.AbstractMap.apply(Map.scala:59)
at isabelle.HTML$.font_face$1(html.scala:366)
at isabelle.HTML$.$anonfun$fonts_css$1(html.scala:371)
at scala.collection.immutable.List.map(List.scala:282)
at isabelle.HTML$.fonts_css(html.scala:371)
at isabelle.Present$.output_document$1(present.scala:120)
at isabelle.Present$.preview(present.scala:138)
at isabelle.vscode.Preview_Panel.$anonfun$flush$2(preview_panel.scala:33)
at scala.collection.TraversableOnce.$anonfun$foldLeft$1(TraversableOnce.scala:156)
at scala.collection.TraversableOnce.$anonfun$foldLeft$1$adapted(TraversableOnce.scala:156)
at scala.collection.Iterator.foreach(Iterator.scala:937)
at scala.collection.Iterator.foreach$(Iterator.scala:937)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1425)
at scala.collection.TraversableOnce.foldLeft(TraversableOnce.scala:156)
at scala.collection.TraversableOnce.foldLeft$(TraversableOnce.scala:154)
at scala.collection.AbstractIterator.foldLeft(Iterator.scala:1425)
at scala.collection.TraversableOnce.$div$colon(TraversableOnce.scala:150)
at scala.collection.TraversableOnce.$div$colon$(TraversableOnce.scala:150)
at scala.collection.AbstractIterator.$div$colon(Iterator.scala:1425)
at isabelle.vscode.Preview_Panel.$anonfun$flush$1(preview_panel.scala:27)
at isabelle.Synchronized.change_result(synchronized.scala:73)
at isabelle.vscode.Preview_Panel.flush(preview_panel.scala:24)
at isabelle.vscode.Server.$anonfun$delay_preview$2(server.scala:210)
at isabelle.Standard_Thread$Delay.run(standard_thread.scala:64)
at isabelle.Standard_Thread$Delay.$anonfun$invoke$1(standard_thread.scala:77)
at isabelle.Event_Timer$$anon$1.run(event_timer.scala:27)
at java.base/java.util.TimerThread.mainLoop(Timer.java:556)
at java.base/java.util.TimerThread.run(Timer.java:506)
If I then do anything else (for example typing in the code window) another exception is raised every time
[Error - 9:01:48 PM] java.lang.IllegalStateException: Timer already cancelled.
How can I get rid of these two errors?
I found the same or a similar problem here, and they recommend running
$ isabelle scala
scala> import isabelle._
scala> Isabelle_Fonts.fonts(hidden = true)
Which results in
res0: List[isabelle.Isabelle_Fonts.Entry] = List(Entry("/home/daniel/opt/isabelle/contrib/isabelle_fonts-20190409/ttf-hinted/IsabelleDejaVuSans.ttf",false), Entry("/home/daniel/opt/isabelle/contrib/isabelle_fonts-20190409/ttf-hinted/IsabelleDejaVuSans-Bold.ttf",false), Entry("/home/daniel/opt/isabelle/contrib/isabelle_fonts-20190409/ttf-hinted/IsabelleDejaVuSans-Oblique.ttf",false), Entry("/home/daniel/opt/isabelle/contrib/isabelle_fonts-20190409/ttf-hinted/IsabelleDejaVuSans-BoldOblique.ttf",false), Entry("/home/daniel/opt/isabelle/contrib/isabelle_fonts-20190409/ttf-hinted/IsabelleDejaVuSansMono.ttf",false), Entry("/home/daniel/opt/isabelle/contrib/isabelle_fonts-20190409/ttf-hinted/IsabelleDejaVuSansMono-Bold.ttf",false), Entry("/home/daniel/opt/isabelle/con...
The plain answer: Isabelle2019 does not support VSCode --- that platform is moving too fast and assuming quick movements.
In Isabelle2020 (April 2020) it should work again. Approximations of this release is available here: https://sketis.net/2020/release-process-for-isabelle2020
See also https://marketplace.visualstudio.com/items?itemName=makarius.Isabelle2020

Finding Scala libraries location from within Scala program

I'm trying to make one Scala program spawn another Scala program. I managed to obtain java executable from System.getProperty("java.home"), I've obtained some path from System.getProperty("java.class.path") (sbt-launcher.jar location), and with ClassLoader I've got project/target/scala-2.11/classes directory.
However, I am still unable to run it. JVM complain that it is unable to find Scala library's classes:
Exception in thread "main" java.lang.NoClassDefFoundError: scala/concurrent/ExecutionContext
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException: scala.concurrent.ExecutionContext
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 7 more
I am looking for a way to add those files to classpath, but I want it to be portable. I do not look for solutions like hardcoding scala location on local computer nor do I want to use other environment variables and parameters than the one already existing. I also don't want to rely on SBT or Activators presence in user's environment.
Since the parent JVM process can use them their location has to be stored somewhere and I'll be thankful for help with finding out that location.
To successfully spawn one Scala App from another I had to fix several issues with my code:
1. correct main class:
object ChildApp extends App {
println("success")
}
to make sure that ChildApp is runnable by Java it has to be an object. Scala has no concept of static but object methods would (and main will) be compiled into static method.
2. correct class name:
While ChildApp.getClass.getName returns ChildApp$, it refers to an object (so that we could pass otherwise static-method-only class around). Java expects $ in command line - in other works I had to remove tailing $ before passing it into the process builder.
3. complete class path
I haven't found all used JARs within System.getPropertiy("java.class.path"):
val pcp = System getPropertiy "java.class.path" split File.pathSeparator // sbt-launcher.jar only
I haven't found them in SystemClassLoader either:
val scp = ClassLoader.getSystemClassLoader.asInstanceOf[URLClassLoader].getURLs.map(_.toString) // same as above
I did found compiled files from my project using Class' resources:
// format like jar:file:/(your-project/compiled.jar)!some/package/ChildApp.class
lazy val jarClassPathPattern = "jar:(file:)?([^!]+)!.+".r
// format like file:/(your-project/compiled/some/package/ChildApp).class
lazy val fileClassPathPattern = "file:(.+).class".r
val jcp = jarClassPathPattern.findFirstMatchIn(pathToClass) map { matcher =>
val jarDir = Paths get (matcher group 2) getParent()
s"${jarDir}/*"
} toSet
val fcp = fileClassPathPattern.findFirstMatchIn(pathToClass) map { matcher =>
val suffix = "/" + clazz.getName
val fullPath = matcher group 1
fullPath substring (0, fullPath.length - suffix.length)
} toList
Finally I found where all those dependencies where stored:
// use App class' ClassLoader instead of system one
val lcp = ChildApp.getClass.getClassLoader.asInstanceOf[URLClassLoader].getURLs.map(_.toString)
4. bonus - JVM params and java location
val jvmArgs = ManagementFactory.getRuntimeMXBean.getInputArguments.toList
lazy val javaHome = System getProperty "java.home"
lazy val java = Seq(
Paths.get(javaHome, "bin", "java"),
Paths.get(javaHome, "bin", "java.exe")
) filter (Files exists _) head
Then you have everything you need for ProcessBuilder / Process:
val executable = java.toString
val arguments = jvmArgs ++ List("-cp", classPath, mainName) ++ mainClassArguments
PS. I checked several times - those additional JARs aren't passed using neither CLASSPATH environment variable nor with -cp parameter (sbt-launcher.jar's MANIFEST file did't had anything as well). So anyone knowing how they are passed and why my solution actually works, please explain.

IDEA Scala: Could not find output directory

Trying to play with scala in IDEA with scala plug-in:
My HelloWorld object:
object HelloWorld {
def main(args: Array[String]) {
println("Hello")
}
}
And sometimes I getting next error when pressing 'Run HelloWorld' from context menu.
scalac: Error: Could not find an output directory for /Users/username/Work/src/sandbox/src/HelloWorld.scala in List((/Users/username/work/src/sandbox/src,/Users/username/work/src/sandbox/out/production/sandbox))
scala.reflect.internal.FatalError: Could not find an output directory for /Users/username/Work/src/sandbox/src/HelloWorld.scala in List((/Users/username
/work/src/sandbox/src,/Users/username/work/src/sandbox/out/production/sandbox))
at scala.tools.nsc.settings.MutableSettings$OutputDirs.outputDirFor(MutableSettings.scala:303)
at scala.tools.nsc.backend.jvm.BytecodeWriters$class.outputDirectory(BytecodeWriters.scala:26)
at scala.tools.nsc.backend.jvm.BytecodeWriters$class.scala$tools$nsc$backend$jvm$BytecodeWriters$$getFile(BytecodeWriters.scala:37)
at scala.tools.nsc.backend.jvm.BytecodeWriters$ClassBytecodeWriter$class.writeClass(BytecodeWriters.scala:89)
at scala.tools.nsc.backend.jvm.GenASM$AsmPhase$$anon$4.writeClass(GenASM.scala:67)
at scala.tools.nsc.backend.jvm.GenASM$JBuilder.writeIfNotTooBig(GenASM.scala:458)
at scala.tools.nsc.backend.jvm.GenASM$JMirrorBuilder.genMirrorClass(GenASM.scala:2954)
at scala.tools.nsc.backend.jvm.GenASM$AsmPhase.run(GenASM.scala:113)
at scala.tools.nsc.Global$Run.compileUnitsInternal(Global.scala:1583)
at scala.tools.nsc.Global$Run.compileUnits(Global.scala:1557)
at scala.tools.nsc.Global$Run.compileSources(Global.scala:1553)
at scala.tools.nsc.Global$Run.compile(Global.scala:1662)
at xsbt.CachedCompiler0.run(CompilerInterface.scala:126)
at xsbt.CachedCompiler0.run(CompilerInterface.scala:102)
at xsbt.CompilerInterface.run(CompilerInterface.scala:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at sbt.compiler.AnalyzingCompiler.call(AnalyzingCompiler.scala:102)
at sbt.compiler.AnalyzingCompiler.compile(AnalyzingCompiler.scala:48)
at sbt.compiler.AnalyzingCompiler.compile(AnalyzingCompiler.scala:41)
at org.jetbrains.jps.incremental.scala.local.IdeaIncrementalCompiler.compile(IdeaIncrementalCompiler.scala:26)
at org.jetbrains.jps.incremental.scala.local.LocalServer.compile(LocalServer.scala:25)
at org.jetbrains.jps.incremental.scala.remote.Main$.make(Main.scala:58)
at org.jetbrains.jps.incremental.scala.remote.Main$.nailMain(Main.scala:21)
at org.jetbrains.jps.incremental.scala.remote.Main.nailMain(Main.scala)
at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.martiansoftware.nailgun.NGSession.run(NGSession.java:319)
This error very annoying because to fix it I need to restart IDEA, clean/compile my project, add/remove launch configuration few times. Also command line from the error properly can be executed from the terminal manually.
Looking at the error comment:
Could not find an output directory for:
/Users/username/Work/src/sandbox/src/HelloWorld.scala
in
/Users/username/work/src/sandbox/src
/Users/username/work/src/sandbox/out/production/sandbox
Depending on the environment you're running the IntelliJ in the upper/lower case difference matters. Please make sure your user.home property is set correctly.
Answer from Norbert Radyk didn't apply to me. Paths were correct in my case. I had to delete target/scala-2.11/test-classes folder in order to compel Intellij to recompile the test class. A bit of a pain though as it will work as long as I don't have to modify the test itself. So not really a solution but a bit of a hack in case you really need to debug a test.

Scala on Mac - Cannot figure out how to run target?

I'm attempting to run a Scala script that imports scala.IO.Source, which throws an exception every time I try to run it as follows:
Exception in thread "main" java.lang.RuntimeException: Cannot figure out how to run target: countchars1.scala
at scala.sys.package$.error(package.scala:27)
at scala.tools.nsc.GenericRunnerCommand.scala$tools$nsc$GenericRunnerCommand$$guessHowToRun(GenericRunnerCommand.scala:38)
at scala.tools.nsc.GenericRunnerCommand$$anonfun$2.apply(GenericRunnerCommand.scala:48)
at scala.tools.nsc.GenericRunnerCommand$$anonfun$2.apply(GenericRunnerCommand.scala:48)
at scala.Option.getOrElse(Option.scala:108)
at scala.tools.nsc.GenericRunnerCommand.<init>(GenericRunnerCommand.scala:48)
at scala.tools.nsc.GenericRunnerCommand.<init>(GenericRunnerCommand.scala:17)
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:33)
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:89)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
I believe it is due to my Path or Classpath settings but I'm unsure what these need to be or where they need to be set. I have tried amending .bash_profile to no avail and have tried adding .profile with what I believe to be the required PATH settings but there doesn't appear to be a straight answer to this that I can find
I'm currently running Scala 2.9.1 on a Mac OSX 10.6. The script I'm trying to run from 'Programming in Scala' is as follows:
import scala.io.Source
if (args.length > 0) {
for (line <- Source.fromFile(args(0)).getLines)
print(line.length +" "+ line)
}
else
Console.err.println("Please enter filename")
I encounter the exception when I type the following in the terminal window:
$ scala countchars1.scala countchars1.scala
Any help with this would be much appreciated.
Managed to solve the issue by setting the JAVA_HOME variable using the following instructions:
http://decoding.wordpress.com/2010/02/26/how-to-set-the-java_home-variable-in-mac-os-x-snow-leopard/

How can I get complete stacktraces for exceptions thrown in tests when using sbt and testng?

The stacktraces are truncated - e.g. they end with [info] ...
Using last or changing traceLevel doesn't help - it simply prints the complete stacktrace of the sbt wrapper.
This is testing with testng (also I believe using scalatest and sl4j)
Using hints found in the documentation here:
(quoted)
You can configure the output shown when running with sbt in four ways: 1) turn off color, 2) show short stack traces, 3) full stack traces, and 4) show durations for everything. To do so you must pass a -o argument to ScalaTest, and after the -o, place any combination of:
D - show durations
S - show short stack traces
F - show full stack traces
W - without color
For example, "-oDF" would show full stack traces and durations (the amount of time spent in each test).
To pass arguments from sbt to ScalaTest you can either add test options globally, like this:
testOptions in Test += Tests.Argument("-oD")
(See the website for the rest of the quote)
You can use the following sbt command to enable full stack traces in tests:
> set testOptions in YourProjectName += Tests.Argument("-oF")
Per Sasha's comment, this can also be done from the command line per test run as shown below.
$ sbt test -- -oF
As an alternative to getting SBT to print the full stack trace, could you put a try-catch block around your test runner? For example, from the REPL:
scala> try { throw new Exception } catch { case e => e }
res1: java.lang.Throwable = java.lang.Exception
scala> res1.printStackTrace
java.lang.Exception
at $line2.$read$$iw$$iw$.liftedTree1$1(<console>:8)
at $line2.$read$$iw$$iw$.<init>(<console>:8)
at $line2.$read$$iw$$iw$.<clinit>(<console>)
...