Skip to content

Commit 399835d

Browse files
viper-data-collection changes (#766)
* moved code to fork * added new submitter * added new setter * changed manualsubmitter * added helper function * moved function to trait * removed default ip * removed user file names * rewrote some docs * added missing overrides
1 parent 7059da7 commit 399835d

3 files changed

Lines changed: 187 additions & 0 deletions

File tree

build.sbt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ lazy val silver = (project in file("."))
5454
libraryDependencies += "org.jgrapht" % "jgrapht-core" % "1.5.0", // Graphs
5555
libraryDependencies += "org.slf4j" % "slf4j-api" % "1.7.30", // Logging
5656
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3", // Logging
57+
libraryDependencies += "com.lihaoyi" %% "requests" % "0.3.0", // Data collection
58+
libraryDependencies += "com.lihaoyi" %% "upickle" % "1.0.0", // Data collection
5759

5860
// Test settings.
5961
Test / parallelExecution := false,

src/main/scala/viper/silver/frontend/SilFrontEndConfig.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ abstract class SilFrontendConfig(args: Seq[String], private var projectName: Str
139139
hidden = false
140140
)
141141

142+
val submitForEvaluation = opt[Boolean](name = "submitForEvaluation",
143+
descr = "Whether to allow storing the current program for future evaluation.",
144+
default = Some(false),
145+
noshort = true
146+
)
147+
142148
validateOpt(file, ignoreFile) {
143149
case (_, Some(true)) => Right(())
144150
case (Some(filepath), _) => validateFileOpt(file.name, filepath)
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
package viper.silver.utility
2+
3+
import scala.io.Source.fromFile
4+
import ujson.{Arr, Obj}
5+
import viper.silver.ast.Program
6+
import viper.silver.ast.pretty.FastPrettyPrinter
7+
import viper.silver.verifier.{Success, VerificationResult}
8+
import viper.silver.frontend.{SilFrontend}
9+
10+
/** Trait for an object that submits a program to the viper-data-collection API */
11+
trait ProgramSubmitter {
12+
13+
/** Protocol, IP address and port of server hosting the viper-data-collection API */
14+
val API_HOST = ""
15+
16+
/** Whether program will be submitted to database */
17+
protected def allowSubmission: Boolean
18+
19+
/** Plaintext Viper program that was verified */
20+
protected def program: String
21+
22+
/** Frontend that generated program, if manually submitted to Silicon and Carbon this should be equal to [[originalVerifier]] */
23+
protected def originalFrontend: String
24+
25+
/** Arguments passed to the verifier */
26+
protected def args: Array[String]
27+
28+
/** Verifier used to verify program */
29+
protected def originalVerifier: String
30+
31+
/** Was verification successful*/
32+
protected def succeeded: Boolean
33+
34+
/** Time between verification start and end */
35+
protected def runtime: Long
36+
37+
/** Sends program and metadata to viper-data-collection API */
38+
def submit(): Unit = {
39+
if (API_HOST != "" && allowSubmission) {
40+
val submission =
41+
Obj(
42+
"program" -> program,
43+
"frontend" -> originalFrontend,
44+
"args" -> Arr.from[String](args),
45+
"originalVerifier" -> originalVerifier,
46+
"success" -> succeeded,
47+
"runtime" -> runtime
48+
)
49+
try {
50+
requests.post(s"$API_HOST/submit-program", data = submission)
51+
} catch {
52+
case _: Exception => println("Program couldn't be submitted")
53+
}
54+
}
55+
}
56+
57+
def programToString(p: Program): String = FastPrettyPrinter.pretty(p)
58+
59+
protected def didVerSucceed(vr: Option[VerificationResult]): Boolean =
60+
vr match {
61+
case Some(res) =>
62+
res match {
63+
case Success => true
64+
case _ => false
65+
}
66+
case _ => false
67+
}
68+
69+
}
70+
71+
/** To use when no [[SilFrontend]] is available.
72+
*
73+
* Methods to call before calling [[submit]]: [[setProgram]] and [[setSuccess]]
74+
*/
75+
class ManualProgramSubmitter(
76+
var allowSubmission: Boolean,
77+
var program: String,
78+
var originalFrontend: String,
79+
var originalVerifier: String,
80+
var args: Array[String]
81+
) extends ProgramSubmitter {
82+
83+
private val startTime: Long = System.currentTimeMillis()
84+
protected var succeeded: Boolean = false
85+
86+
def setAllowSubmission(b: Boolean): Unit = allowSubmission = b
87+
88+
def setProgram(p: String): Unit = program = p
89+
90+
def setProgram(p: Program): Unit = program = programToString(p)
91+
92+
def setSuccess(success: Boolean): Unit = succeeded = success
93+
94+
override def runtime: Long = System.currentTimeMillis() - startTime
95+
}
96+
97+
/** ProgramSubmitter that takes a [[SilFrontend]] to read out verification metrics, so they don't have to be manually defined.
98+
* Assumes submit will be called after verification is finished.
99+
*/
100+
trait FEProgramSubmitter extends ProgramSubmitter {
101+
102+
var args: Array[String] = Array()
103+
104+
/** Instance of frontend responsible for verification, used to read out verification metrics */
105+
protected val frontend: SilFrontend
106+
107+
override def allowSubmission: Boolean =
108+
frontend.config.submitForEvaluation.getOrElse(false)
109+
110+
override def originalFrontend: String = originalVerifier
111+
112+
override def originalVerifier: String = frontend.getVerifierName.capitalize
113+
114+
override def succeeded: Boolean = didVerSucceed(frontend.getVerificationResult)
115+
116+
override def runtime: Long = frontend.getTime
117+
118+
def setArgs(arguments: Array[String]): Unit = {
119+
args =
120+
arguments.filter(a => a != "--submitForEvaluation" && !a.endsWith(".vpr"))
121+
}
122+
}
123+
124+
/** [[FEProgramSubmitter]] implementation that assumes program is available in local file.
125+
*
126+
* Methods to call before calling [[submit]]: [[setArgs]]
127+
*/
128+
class FileProgramSubmitter(fe: SilFrontend) extends FEProgramSubmitter {
129+
130+
private var programPath: String = ""
131+
protected val frontend: SilFrontend = fe
132+
133+
override def program: String = {
134+
readFileContent(programPath)
135+
}
136+
137+
override def setArgs(arguments: Array[String]): Unit = {
138+
programPath = arguments.find(_.endsWith(".vpr")) match {
139+
case Some(p) => p
140+
case None => ""
141+
}
142+
super.setArgs(arguments)
143+
}
144+
145+
protected def readFileContent(file: String): String = {
146+
try {
147+
val fBuffer = fromFile(file)
148+
val content =
149+
try {
150+
fBuffer.mkString
151+
} catch {
152+
case _: Exception => ""
153+
} finally fBuffer.close()
154+
content
155+
} catch {
156+
case _: Exception => ""
157+
}
158+
}
159+
}
160+
161+
/** [[FEProgramSubmitter]] implementation that creates a submission from a program AST, for cases where no local file is available.
162+
*
163+
* Methods to call before calling [[submit]]: [[setProgram]] and [[setArgs]]
164+
*/
165+
class ViperProgramSubmitter(fe: SilFrontend) extends FEProgramSubmitter {
166+
private var viperProgram: Program = null
167+
protected val frontend = fe
168+
169+
def setProgram(p: Program): Unit = {
170+
viperProgram = p
171+
}
172+
173+
override def program: String = {
174+
if (viperProgram != null) {
175+
programToString(viperProgram)
176+
} else ""
177+
}
178+
179+
}

0 commit comments

Comments
 (0)