Skip to content

Commit 9f1e95e

Browse files
authored
Fixing variable counterexamples and adding tests (#915)
1 parent e8dbeef commit 9f1e95e

4 files changed

Lines changed: 61 additions & 30 deletions

File tree

src/main/scala/interfaces/Verification.scala

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import viper.silicon.debugger.{DebugAxiom, DebugExp, DebugExpPrintConfiguration}
1010
import viper.silicon.common.collections.immutable.InsertionOrderedSet
1111
import viper.silicon.interfaces.state.Chunk
1212
import viper.silicon.reporting._
13-
import viper.silicon.state.terms.{FunctionDecl, MacroDecl, Term}
13+
import viper.silicon.state.terms.{BooleanLiteral, FunctionDecl, IntLiteral, MacroDecl, Term, Var}
1414
import viper.silicon.state.{State, Store}
1515
import viper.silicon.verifier.Verifier
1616
import viper.silver.ast
@@ -166,11 +166,22 @@ case class SiliconNativeCounterexample(internalStore: Store, heap: Iterable[Chun
166166

167167
case class SiliconVariableCounterexample(internalStore: Store, nativeModel: Model) extends SiliconCounterexample {
168168
override val model: Model = {
169-
Model(internalStore.values.filter{
170-
case (_,v) => nativeModel.entries.contains(v.toString)
171-
}.map{
172-
case (k, v) => k.name -> nativeModel.entries(v.toString)
173-
})
169+
val variableValues = internalStore.values.filter {
170+
case (_, (v: Var, _)) => nativeModel.entries.contains(v.toString)
171+
case _ => false
172+
}.map {
173+
case (k, (v, _)) => k.name -> nativeModel.entries(v.toString)
174+
}
175+
val constantValues = internalStore.values.filter {
176+
case (_, (_: IntLiteral, _)) => true
177+
case (_, (_: BooleanLiteral, _)) => true
178+
case _ => false
179+
}.map {
180+
case (k, (i: IntLiteral, _)) => k.name -> ConstantEntry(i.toString)
181+
case (k, (b: BooleanLiteral, _)) => k.name -> ConstantEntry(b.toString)
182+
}
183+
184+
Model(variableValues ++ constantValues)
174185
}
175186

176187
override def withStore(s: Store): SiliconCounterexample = {

src/test/scala/CounterexampleTests.scala

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@
77
package viper.silicon.tests
88

99
import viper.silicon.Silicon
10-
import viper.silver.testing.{AbstractOutput, CustomAnnotation, DefaultAnnotatedTestInput, DefaultTestInput, OutputAnnotationId, SilOutput, TestAnnotation, TestAnnotationParser, TestCustomError, TestError, TestInput}
10+
import viper.silver.testing.{AbstractOutput, CounterexampleParser, CustomAnnotation, DefaultAnnotatedTestInput, DefaultTestInput, ExpectedCounterexample, OutputAnnotationId, SilOutput, TestAnnotation, TestAnnotationParser, TestCustomError, TestError, TestInput}
1111
import fastparse._
1212
import viper.silicon.interfaces.SiliconMappedCounterexample
1313
import viper.silicon.reporting.{ExtractedModel, ExtractedModelEntry, LitIntEntry, LitPermEntry, NullRefEntry, RecursiveRefEntry, RefEntry, SeqEntry}
14-
import viper.silver.parser.FastParserCompanion.whitespace
1514
import viper.silver.parser.{FastParser, PAccPred, PBinExp, PExp, PFieldAccess, PIdnUseExp, PIntLit, PLookup, PSymOp, PUnExp}
1615
import viper.silver.utility.Common.Rational
1716
import viper.silver.verifier.{FailureContext, VerificationError}
@@ -167,24 +166,3 @@ case class ExpectedCounterexampleAnnotation(id: OutputAnnotationId, file: Path,
167166

168167
override def withForLineNr(line: Int = forLineNr): ExpectedCounterexampleAnnotation = ExpectedCounterexampleAnnotation(id, file, line, expectedCounterexample)
169168
}
170-
171-
/**
172-
* Simple input language to describe an expected counterexample with corresponding parser.
173-
* Currently, a counterexample is expressed by a comma separated list of access predicates and equalities (using the
174-
* same syntax as in Viper)
175-
*/
176-
class CounterexampleParser(fp: FastParser) {
177-
import fp.{accessPred, eqExp}
178-
179-
def expectedCounterexample[_: P]: P[ExpectedCounterexample] =
180-
(Start ~ "(" ~ (accessPred | eqExp).rep(0, ",") ~ ")" ~ End)
181-
.map(ExpectedCounterexample)
182-
}
183-
184-
case class ExpectedCounterexample(exprs: Seq[PExp]) {
185-
assert(exprs.forall {
186-
case _: PAccPred => true
187-
case PBinExp(_, r, _) if r.rs == PSymOp.EqEq => true
188-
case _ => false
189-
})
190-
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
//
5+
// Copyright (c) 2011-2025 ETH Zurich.
6+
7+
package viper.silicon.tests
8+
9+
import viper.silicon.Silicon
10+
import viper.silver.testing.{CounterexampleComparison, CounterexampleVariablesTests, ExpectedCounterexample, ExpectedValuesCounterexampleAnnotation, OutputAnnotationId, TestCustomError, TestError}
11+
import viper.silicon.interfaces.SiliconVariableCounterexample
12+
import viper.silver.verifier.FailureContext
13+
14+
import java.nio.file.Path
15+
16+
class SiliconCounterexampleVariablesTests extends SiliconTests with CounterexampleVariablesTests {
17+
18+
override def configureVerifiersFromConfigMap(configMap: Map[String, Any]): Unit = {
19+
val args = Silicon.optionsFromScalaTestConfigMap(prefixSpecificConfigMap(configMap).getOrElse("silicon", Map()))
20+
val additionalArgs = Seq("--counterexample=variables", "--exhaleMode=1")
21+
22+
silicon.parseCommandLine(args ++ additionalArgs :+ Silicon.dummyInputFilename)
23+
}
24+
25+
override def createExpectedValuesCounterexampleAnnotation(id: OutputAnnotationId, file: Path, forLineNr: Int, expectedCounterexample: ExpectedCounterexample): ExpectedValuesCounterexampleAnnotation =
26+
SiliconExpectedValuesCounterexampleAnnotation(id, file, forLineNr, expectedCounterexample)
27+
}
28+
29+
/** represents an expected output (identified by `id`) with an associated (possibly partial) counterexample model */
30+
case class SiliconExpectedValuesCounterexampleAnnotation(id: OutputAnnotationId, file: Path, forLineNr: Int, expectedCounterexample: ExpectedCounterexample) extends
31+
ExpectedValuesCounterexampleAnnotation(id, file, forLineNr, expectedCounterexample) {
32+
33+
def containsExpectedCounterexample(failureContext: FailureContext): Boolean =
34+
failureContext.counterExample match {
35+
case Some(silCounterexample: SiliconVariableCounterexample) => CounterexampleComparison.meetsExpectations(expectedCounterexample, silCounterexample.model)
36+
case _ => false
37+
}
38+
39+
override def notFoundError: TestError = TestCustomError(s"Expected the following counterexample on line $forLineNr: $expectedCounterexample")
40+
41+
override def withForLineNr(line: Int = forLineNr): ExpectedValuesCounterexampleAnnotation = SiliconExpectedValuesCounterexampleAnnotation(id, file, line, expectedCounterexample)
42+
}

0 commit comments

Comments
 (0)