Skip to content

Commit

Permalink
Various improvements/fixes to the unit tests:
Browse files Browse the repository at this point in the history
 - refactored commonly used operations into TestHelpers.scala
 - build.sbt:
     * disabled running tests in parallel (caused nondeterministic test failures; resolver/typechecker seems to not be thread-safe)
     * pre-load SLF4J logger factory to prevent racy initialisation problems of Logback
 - disabled a test for the domain instance generation code (looks plain wrong)
 - renamed a misspelled test directory (hygienicMacros)
 - worked around a nondeterminism issue in a regex rewriter test
  • Loading branch information
mschwerhoff committed Apr 28, 2017
1 parent 048610f commit b6492ea
Show file tree
Hide file tree
Showing 27 changed files with 409 additions and 541 deletions.
11 changes: 11 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,14 @@ scalacOptions ++= Seq("-Ypatmat-exhaust-depth", "off")
// allows them to access the Sil test suite.
publishArtifact in Test := true
//(Test, packageBin) := true

// Avoid problems with racy initialisation of SLF4J:
// http://stackoverflow.com/a/12095245
// https://github.com/typesafehub/scalalogging/issues/23
testOptions in Test += Tests.Setup(classLoader =>
classLoader
.loadClass("org.slf4j.LoggerFactory")
.getMethod("getLogger", classLoader.loadClass("java.lang.String"))
.invoke(null, "ROOT"))

parallelExecution in Test := false
51 changes: 25 additions & 26 deletions src/main/scala/viper/silver/ast/utility/DomainInstances.scala
Original file line number Diff line number Diff line change
Expand Up @@ -301,32 +301,31 @@ object DomainInstances {
t.substitute(s)
}

// def showInstanceMembers(p: Program): Unit = {
//// println("================== Domain instances")
// for (ti <- p.groundTypeInstances) {
///* ti match {
// case dt: DomainType =>
// println("Members for Domain type " + dt.toString())
// val domain = p.findDomain(dt.domainName)
// val (fs, as) = getInstanceMembers(p, dt)
// // val sfs = domain.functions.map(substitute(_,dt.typVarsMap,p))
// for (f <- fs)
// println(" " + f.toString())
// for (a <- as)
// println(" " + a.toString())
// for (rf <- domain.functions.filter(f => fs.forall((ff) => ff.name != f.name)))
// println(" Rejected " + substitute(rf, dt.typVarsMap, p).toString())
// for (ra <- domain.axioms.filter(a => as.forall((aa) => aa.name != a.name)))
// println(" Rejected " + substitute(ra, dt.typVarsMap, p).toString())
// case _ =>
// }
//*/
// }
//// println("================== Domain instances done")
// /* val allTypes = collectGroundTypes(p,p)
// for (t <- allTypes)
// println(t.toString())*/
// }
def showInstanceMembers(p: Program): Unit = {
println("================== Domain instances")
for (ti <- p.groundTypeInstances) {
ti match {
case dt: DomainType =>
println("Members for Domain type " + dt.toString())
val domain = p.findDomain(dt.domainName)
val (fs, as) = getInstanceMembers(p, dt)
// val sfs = domain.functions.map(substitute(_,dt.typVarsMap,p))
for (f <- fs)
println(" " + f.toString())
for (a <- as)
println(" " + a.toString())
for (rf <- domain.functions.filter(f => fs.forall((ff) => ff.name != f.name)))
println(" Rejected " + substitute(rf, dt.typVarsMap, p).toString())
for (ra <- domain.axioms.filter(a => as.forall((aa) => aa.name != a.name)))
println(" Rejected " + substitute(ra, dt.typVarsMap, p).toString())
case _ =>
}
}
println("================== Domain instances done")
val allTypes = collectGroundTypes(p,p)
for (t <- allTypes)
println(t.toString())
}

def getFTVDepths(t: Type): Map[TypeVar, Int] = t match {
case dt: DomainType =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

package viper.silver.ast.utility.Rewriter

import viper.silver.ast.QuantifiedExp

/**
* Extension of the Strategy context. Encapsulates all the required information for the rewriting
*
Expand Down Expand Up @@ -187,7 +185,7 @@ class RegexStrategy[N <: Rewritable, COLL](a: TRegexAutomaton, p: PartialFunctio
// Marked for rewrite
case MarkedForRewrite() => newMarked = newMarked ++ Seq((n.asInstanceOf[N], newCtxt))
// Context update
case ContextInfo(c: Any) => newCtxt = newCtxt.update(c.asInstanceOf[COLL])
case ContextInfo(c: Any) => newCtxt = newCtxt.update(c.asInstanceOf[COLL]) /* TODO: This cast is *not* guaranteed to succeed! */
// Only recurse if we are the selected child
case ChildSelectInfo(r: Rewritable) => newChildren.filter(_ eq r)
}
Expand Down Expand Up @@ -259,4 +257,4 @@ class RegexStrategy[N <: Rewritable, COLL](a: TRegexAutomaton, p: PartialFunctio
}

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ function NonDet2(vari1:Bool, vari2:Bool): Bool {
}

function func(b: Bool): Bool
ensures exists k: Bool :: true || (b && (k || exists j: Bool :: true || j)) {
ensures exists k: Bool :: true || (b && (k || exists m: Bool :: true || m)) {
true
}

method foo() returns ()
ensures exists k: Bool :: k || true
{

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ function NonDet2(vari1:Bool, vari2:Bool): Bool {
}

function func(b: Bool): Bool
ensures exists k: Bool ::
[NonDet1(k) ? true : (b &&
[NonDet1(k) ? k : (exists j: Bool ::
[NonDet2(k, j) ? true : j, true || j])
, k || exists j: Bool :: true || j]),
true || (b && (k || exists j: Bool :: true || j))] {
ensures exists k: Bool ::
[NonDet1(k) ? true : (b &&
[NonDet1(k) ? k : (exists m: Bool ::
[NonDet2(k, m) ? true : m, true || m])
, k || exists m: Bool :: true || m]),
true || (b && (k || exists m: Bool :: true || m))] {
true
}

method foo() returns ()
ensures exists k: Bool :: [NonDet1(k) ? k : true, k || true]
{

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ function NonDet1(vari: Bool):Bool {
method main() returns ()
{
var i: Bool := true
var j: Bool := true
var m: Bool := true

assert(exists k: Bool :: (i && (k || j)))
}
assert(exists k: Bool :: (i && (k || m)))
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ function NonDet1(vari: Bool):Bool {
method main() returns ()
{
var i: Bool := true
var j: Bool := true
var m: Bool := true

assert(exists k: Bool :: i && [(NonDet1(k) ? k : j),(k || j)])
}
assert(exists k: Bool :: i && [(NonDet1(k) ? k : m),(k || m)])
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
method main() returns ()
{
var i: Bool := true
var j: Bool := false
var m: Bool := false

assert(i || j)
}
assert(i || m)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
method main() returns ()
{
var i: Bool := true
var j: Bool := false
var m: Bool := false

assert([(true ? i : j), i || j])
}
assert([(true ? i : m), i || m])
}
78 changes: 31 additions & 47 deletions src/test/scala/DomainInstanceTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import java.nio.file.{Path, Paths}
import java.nio.file.Paths

import TestHelpers.MockSilFrontend

import scala.language.implicitConversions
import org.scalatest.{FunSuite, Matchers}
import viper.silver.ast._
import viper.silver.ast.utility._
import viper.silver.frontend.{SilFrontend, TranslatorState}
import viper.silver.verifier.AbstractError

import scala.language.implicitConversions

Expand All @@ -28,7 +28,7 @@ class DomainInstanceTest extends FunSuite with Matchers {
}

test("Basic domain instances 2") {
val frontend = new DummyFrontend
val frontend = new MockSilFrontend
val fileN = "all/domains/domains2.sil"
val fileR = getClass.getResource(fileN)
assert(fileR != null, s"File $fileN not found")
Expand Down Expand Up @@ -63,7 +63,7 @@ class DomainInstanceTest extends FunSuite with Matchers {
}

test("Domain instances recursion threshold") {
val frontend = new DummyFrontend
val frontend = new MockSilFrontend
val fileN = "all/domains/domains_threshold.sil"
val fileR = getClass.getResource(fileN)
assert(fileR != null, s"File $fileN not found")
Expand All @@ -72,49 +72,33 @@ class DomainInstanceTest extends FunSuite with Matchers {

frontend.translate(file) match {
case (Some(p), _) =>
// DomainInstances.showInstanceMembers(p)
// viper.silver.ast.utility.DomainInstances.showInstanceMembers(p)
p.groundTypeInstances.size should be(8)

for (gi <- p.groundTypeInstances)
gi match {
case dt: DomainType => {
dt.domainName should not be "D1"
}
case _ =>
}

p.groundTypeInstances.count(
_ match { case dt: DomainType => dt.domainName == "D10" && dt.typVarsMap.values.forall(_ == Int)
case _ => false
}
) should be(1)
p.groundTypeInstances.count(
_ match { case dt: DomainType => dt.domainName == "D10"
case _ => false
}
) should be(256)

case _ =>
/* 2017-04-28 Malte:
* Deactivated all remaining assertions since they don't make any sense to me
* (and because they fail). In particular, the assertions expect D1 to not be
* instantiated and D10 to be, but D1 is the only domain in domains_threshold.sil.
*/

// for (gi <- p.groundTypeInstances)
// gi match {
// case dt: DomainType => dt.domainName should not be "D1"
// case _ =>
// }

// p.groundTypeInstances.count {
// case dt: DomainType => dt.domainName == "D10" && dt.typVarsMap.values.forall(_ == Int)
// case _ => false
// } should be(1)

// p.groundTypeInstances.count {
// case dt: DomainType => dt.domainName == "D10"
// case _ => false
// } should be(256)

case (None, errors) =>
fail(s"Expected a parsed program, but got: $errors")
}
}
}


class DummyFrontend extends SilFrontend {
def createVerifier(fullCmd: _root_.scala.Predef.String) = ???

def configureVerifier(args: Seq[String]) = ???

def translate(silverFile: Path): (Option[Program], Seq[AbstractError]) = {
_verifier = None
_state = TranslatorState.Initialized

reset(silverFile) //
translate()

//println(s"_program = ${_program}") /* Option[Program], set if parsing and translating worked */
//println(s"_errors = ${_errors}") /* Seq[AbstractError], contains errors, if encountered */

(_program, _errors)
}
}
Loading

0 comments on commit b6492ea

Please sign in to comment.